网上很容易查到jinjia循环加载后端传来的数据到页面上的方法,但是很难搜到怎么通过jinjia获取flask后端传过来的数据给java script的变量赋值,特此记录。
先来看一下我们传输的数据:
@test_bp.route('/test') def test(): role = "admin" permission = ["r1","r2","r3"] project = [ ["project","project","project","non-project","non-project"], ["p1","p2","p3","tool","other"] ] action= { "p1":["a1","a2","a3"], "p2":["b1"], "p3":["c1","c2"], "tool":["design","development"], "other":["please specify"] } return render_template('test.html', action=action,project=project,role=role,premission=permission) 【方法一】:最初找到的方法,非常复杂,根据传来的数据的结构通过Jinjia不断循环
<script> // 在js里先建好空数据 let role = "" let permission = [] let sourceAllProjects = [] let sourceAllActions = {} </script> <!--把jinjia2的变量赋值到js的变量--> <!-- 传一个字符串变量--> <script type="text/javascript"> role = '{{role}}' //记得这里有引号 </script> <!-- 传一个列表变量--> {% for p in permission %} <script type="
安装
npm install pinia --save 1.在main.js中
import { createApp } from "vue"; import App from "./App.vue"; import { createPinia } from "pinia"; const pinia = createPinia(); createApp(App).use(pinia).mount("#app"); 2.创建文件 store/index.js
也存在另一种定义 store 的可用语法。与 Vue 组合式 API 的 setup 函数 相似,我们可以传入一个函数,该函数定义了一些响应式属性和方法,并且返回一个带有我们想暴露出去的属性和方法的对象。我感觉这种形式写着更方便简单。
import { defineStore } from "pinia"; import { ref } from 'vue' export const useStore = defineStore('main',() => { const searchValue = ref(''); const count = ref(0); function onSearchValue() { console.
目录
二叉树
题目
二叉树的最近公共祖先
原题链接
解析
二叉搜索树的最近公共节点
核心思想
答案
重建二叉树
题目链接
解析
核心思想
答案
二叉搜索树的后序遍历序列
原题链接
解析
核心思想
答案
二叉树 该类题目的解决一般是通过节点的遍历去实现,一般是分两种。
一是递归(深度优先),该方法通常代码比较简单,难懂。首先需要确定入参和返回的内容,然后确定层级之间的关系,最后去找递归的出口。
二是广度优先(该方法一般只有可以分层次处理的才能用),该方法代码量多,易懂。首先借助数组存储第一层的节点,然后每次将数组中的节点分批从数组头部取出(当对比2个节点时就一次取2个),处理完后将对应的子节点分批再从数组尾部存入数组(注意需要对比的子节点相邻存入,这样取出正好配对)。递归上述步骤直到数组为空。
注意特殊的二叉树会满足一些条件。
题目 二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]
示例 1:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 输出: 3 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。 示例 2:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 输出: 5 解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。 说明:
随着WEB前端的发展,现在大部分的前端工程师都已经走上了小程序开发的征程,不管是PC端还是手机端,选择一款优秀框架对项目开发都是至关重要的,个人比较喜欢的小程序框架是Vant Weapp
那么今天我们就看看选择下拉框且带有搜索功能的框怎么去实现,其实Vant本身的选择下拉控件是没有索索功能的 需要我们手工合成一个
json中我们导入必要的控件
{ "usingComponents": { "van-search": "vant-weapp/search", "van-popup": "vant-weapp/popup", "van-picker": "vant-weapp/picker" } } 然后我们调请求去那要用户选择的数据列表
这一步就不用我教了吧
CustomerGetAllList({ }).then((src) => { let list = src.data.data; for(let i = 0;i < list.length;i++){ list[i].text = list[i].customerName; list[i].disabled = false } this.setData({ UserList: list }) }) 刚从后端拿回的数据自然是有必要处理一下的,因为van-picker要求数据是
一个对象数组 然后每一个下标对象 要有一个text对象 作为选项名称 有一个
disabled作为默认选中状态
然后我们在data中设置UserSwitch变量 默认值位false 作为这个控件的开关
然后我们需要在js中添加几个事件
//开启控件 UserOn: function(){ this.setData({ UserSwitch: true }) }, //关闭控件 UserShutdown: function(){ this.setData({ UserSwitch: false }) }, //用户选择某个选项后触发事件 UserIdentification(event){ console.
VGN N75pro说明书 1、封面和最后一页
2、第01、02、03
3、第04
4、第05
如果你是用的ubuntu中自带的驱动,你选择一个不带open的版本驱动安装就可以了。真的服了,这个该死的
目录
两种视频处理方式介绍
jave方式
Javacv的方式
两种视频处理方式介绍 一种jave获取视频信息,使用FFmpeg方式截取视频第n帧生成图片 需要下载一个ffmpeg.exe文件一种是通过Javacv的方式获取视频信息和截图 jave方式 public static void main(String[] args) { String videoPath = "D:\\szw\\photo\\test\\55f9e02108b642.mp4"; String ffmpegPath = "src/main/resources/libs/ffmpeg.exe"; getVideoInfo(videoPath); processImg(videoPath, "1", ffmpegPath); } 几种pom依赖 <dependency> <groupId>it.sauronsoftware</groupId> <artifactId>jave</artifactId> <version>1.0.2</version> </dependency> <dependency> <groupId>com.github.dadiyang</groupId> <artifactId>jave</artifactId> <version>1.0.2</version> </dependency> <!-- https://mvnrepository.com/artifact/ws.schild/jave-core --> <dependency> <groupId>ws.schild</groupId> <artifactId>jave-core</artifactId> <version>2.7.3</version> </dependency> VideoUtil: import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; import java.math.RoundingMode; import java.nio.channels.FileChannel; import java.util.HashMap; import java.util.List; import java.
纯CSS实现四种方式文本反差色效果
mix-blend-mode: difference;
clip-path;
background-clip: text, padding-box
outline 是绘制于元素周围的一条线,位于边框边缘的外围,可起到突出元素的作用。
css 样式之 filter 滤镜属性 用法与示例
使用lottie-web封装一个动画组件
lottie-web使用
wow
useEffect(() => { var wow = new WOW({ boxClass: 'wow', animateClass: 'animated', offset: 0, mobile: true, live: false, scrollContainer: ".pictureOver" }) wow.init(); }, []) data-wow-duration(动画持续时间)
data-wow-delay(动画延迟时间)
data-wow-offset(元素的位置露出后距离底部多少像素执行)
data-wow-iteration(动画执行次数)这四个属性可选可不选。
GSAP(GreenSock Animation Platform)是一个从 Flash 时代一直发展到现在的专业动画库,底层使用 JavaScript 实现
Three.js–》Gsap动画库基本使用与原理
aspect-ratio css中设置图片的比例
给 will-change 属性足够的时间做准备
webkit-mask 遮罩层
REACT 使用gsap + ScrollTrigger
import { ScrollTrigger } from 'gsap/ScrollTrigger'; import { MotionPathPlugin } from 'gsap/MotionPathPlugin'; const SysPageTwo = () => { useLayoutEffect(() => { gsap.
往期回顾:YOLOv5源码解读1.0-目录_汉卿HanQ的博客-CSDN博客
学习完源码后,就要开始学习对模型进行改进。其中包括添加注意力机制,更换主干网络,添加损失函数,更换激活函数,更换NMS,更换neck,增加小目标检测层,更换IoU几大部分
目录
1.添加自注意力机制
1.1自注意力机制-SE
1.2自注意力机制-CBAM
1.3自注意力机制-ECA
1.4自注意力机制-SimAM
1.5自注意力机制-SOCA
1.6自注意力机制-EMA
2.更换主干网络
2.1更换主干网络-MobileNetV3
2.2更换主干网络-ShuffleNetV2
2.3更换主干网络-EfficientNetV2
2.4更换主干网络-GhostNet
3.添加损失函数
3.1添加损失函数-EIoU
3.2添加损失函数-AlphaIoU
3.3添加损失函数-SIoU
3.4添加损失函数-WIoU
4.更换激活函数
4.1更换激活函数-SiLU
4.2更换激活函数-ReLU
4.3更换激活函数-ELU
4.4更换激活函数-Hardswish
4.5更换激活函数-Mish
4.6更换激活函数-Softplus
4.7更换激活函数-AconC
5.更换NMS
5.1更换NMS-DIoU-NMS
5.2更换NMS-CIoU-NMS
5.3更换NMS-EIoU-NMS
5.4更换NMS-GIoU-NMS
5.5更换NMS-SIoU-NMS
5.6更换NMS-soft-NMS
6.更换neck
6.1更换neck-BiFPN
7.增加小目标检测层
8.更换IoU
8.1更换IoU-MPDIoU
1.添加自注意力机制 1.1自注意力机制-SE 博客:
1.2自注意力机制-CBAM 博客:
1.3自注意力机制-ECA 博客:
1.4自注意力机制-SimAM 博客:
1.5自注意力机制-SOCA 博客:
1.6自注意力机制-EMA 博客:
2.更换主干网络 2.1更换主干网络-MobileNetV3 博客:
2.2更换主干网络-ShuffleNetV2 博客:
2.3更换主干网络-EfficientNetV2 博客:
2.4更换主干网络-GhostNet 博客:
3.添加损失函数 3.1添加损失函数-EIoU 博客:
3.2添加损失函数-AlphaIoU 博客:
3.3添加损失函数-SIoU 博客:
原文链接: 版本说明
2022.x 分支 适配 Spring Boot 3.0,Spring Cloud 2022.x 版本及以上的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记): (注意,该分支 Spring Cloud Alibaba 版本命名方式进行了调整,未来将对应 Spring Cloud 版本,前三位为 Spring Cloud 版本,最后一位为扩展版本,比如适配 Spring Cloud 2022.0.0 版本对应的 Spring Cloud Alibaba 第一个版本为:2022.0.0.0,第个二版本为:2022.0.0.1,依此类推)
Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version2022.0.0.0-RC2*Spring Cloud 2022.0.03.0.22022.0.0.0-RC1Spring Cloud 2022.0.03.0.0 2021.x 分支 适配 Spring Boot 2.4,Spring Cloud 2021.x 版本及以上的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记)
Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version2021.0.5.0*Spring Cloud 2021.0.52.6.132021.0.4.0Spring Cloud 2021.
文章目录 💬 前言👉 ① `useIntersectionObserver` 简介👉 ② 范例一:元素👉 ③ 范例二:组件总结📃 参考文献往期内容 💨 💬 前言 这些天小温通过互联网自学呢, 发现了个挺有用的 Vue 实用的工具集。它包含了各种各有的 Vue一些常用 函数 / 组件,并对其进行封装。而且用法也更简单了,国内也有对应的中文文档(吐槽: 就是解释性文字比较少,但是胜在有案例,配合案例去使用,也不算难理解!)。
最重要的是,兼容 Vue2 和 Vue3,支持 Typescript。 配合使用,能达到很好的效果!
vueUse - 中文文档网址:https://www.vueusejs.com/
vueUse - github地址: https://github.com/vueuse/vueuse
入门安装: https://www.vueusejs.com/guide/
接下来,就是今天这篇文章要讲的知识点啦! useIntersectionObserver 响应式监听目标元素的可见性,我们可以通过这个函数,监听我们给定目标元素在页面中的可见性。
通过配合 v-if指令,实现组件的异步加载。同时由于引用的组件是异步加载,会导致在打包的时候,被引用的组件会单独被打包成一个文件。
最终目的都是提高页面性能,常用于 “ 首屏加载 ”,当首屏加载内容过多时,可以将处在屏幕可视范围外的组件内容隐藏。 通过 useIntersectionObserver 监听这些组件相对可视窗口的可见性,异步加载这些组件,减少首屏加载的性能损耗!避免首次加载时间过长!
👉 ① useIntersectionObserver 简介 响应式监听目标元素的可见性,通过指定对应目标元素(组件),监听对应元素在可视窗口的可见性,函数返回一个布尔值。
👉 ② 范例一:元素 <div ref="target"> <h1>Hello world</h1> </div> <script> import { ref } from 'vue' import { useIntersectionObserver } from '@vueuse/core' export default { setup() { const target = ref(null) const targetIsVisible = ref(false) const { stop } = useIntersectionObserver( target, ([{ isIntersecting }], observerElement) => { targetIsVisible.
**
ubuntu server **
sudo su vim /etc/ssh/sshd_config # 在 sshd_config 文件里的 “Authentication” 部分加上以下内容 PermitRootLogin yes # 完成以后退出 vim 并保存 service sshd restart # 重启 ssh 服务以应用更改 passwd root # 直接修改 Root 用户的密码 这样重新登陆 ssh 就可以用 Root 登陆了。 ubuntu 桌面版 默认安装Ubuntu都是不允许以root用户进行登录的,想要以root用户进行登录需要进行一些操作,主要是以下几个步骤:
一、 修改文件/usr/share/lightdm/lightdm.conf.d/50-unity-greeter.conf文件,增加两行: greeter-show-manual-login=true all-guest=false 保存 二、 进入/etc/pam.d目录,修改gdm-autologin和gdm-password文件 vi gdm-autologin 注释掉auth required pam_succeed_if.so user != root quiet_success这一行,保存 vi gdm-password 注释掉 auth required pam_succeed_if.so user != root quiet_success这一行,保存 三、 修改/root/.profile文件 vi /root/.
1 DirectX DirectX(Direct eXtension,简称DX)是由微软公司创建的多媒体编程接口,是一种应用程序接口(API)。DirectX可以让以windows为平台的游戏或多媒体程序获得更高的执行效率,加强3D图形和声音效果,并提供设计人员一个共同的硬件驱动标准,让游戏开发者不必为每一品牌的硬件来写不同的驱动程序,也降低用户安装及设置硬件的复杂度。——百度百科
2 DirectX SDK下载 下载链接:微软官方下载链接——DXSDK_Jun10(585MB)
下载后运行安装。安装后的目录结构如下
包括开发用的Include、Lib等,以及提供了Samples。
3 开发环境配置 3.1 VS系列编译器 如果使用VS2015、VS2017等微软系列编译器,在要加入DX的工程的属性页里:
首先,设置C/C++ --常规-附加包含目录,把DX的include目录添加进去
第二,设置链接器-常规-附加库目录,把DX的lib目录添加进去
第三,在链接器-输入-附加依赖项中添加要用到的DX的lib,我用的是D3D9,所以我加入的是这两个:
d3d9.lib d3dx9.lib 如果用D3D10、D3D11等,或者DirectX的其它功能,加入相应的LIB.
3.2 Qt系列编译器 如果使用的是qt编译器,直接在项目的pro文件中添加,我用到D3D9,所以加入以下:
INCLUDEPATH += "D:/Program Files (x86)/Microsoft DirectX SDK (June 2010)"/include LIBS += "D:/Program Files (x86)/Microsoft DirectX SDK (June 2010)"/Lib/x64/d3d9.lib LIBS += "D:/Program Files (x86)/Microsoft DirectX SDK (June 2010)"/Lib/x64/d3dx9.lib
C语言中的字符串输出操作详解 1. 介绍 在C语言中,字符串输出是常见的操作。本篇博客将详细讨论如何使用printf和puts函数输出字符串,以及字符串中的\0字符和字符串操作结束标志的作用。
2. 使用printf输出字符串 #include <stdio.h> int main() { char str[] = "hello c3"; printf("%s", str); return 0; } 输出结果:hello c3
3. printf与常量字符串的输出 #include <stdio.h> int main() { printf("hello c3"); return 0; } 输出结果:hello c3
4. 使用puts输出字符串 #include <stdio.h> int main() { char str[] = "hello c3"; puts(str); return 0; } 输出结果:hello c3
5. 字符数组中的\0和字符串操作结束标志 #include <stdio.h> int main() { char str[] = "hello\0c3"; // \0作为字符串的结束标志 printf("%s", str); return 0; } 输出结果:hello
文章来源:WorkMap技术博客-Docker Build
关于Docker Build Docker Build 是 Docker 引擎最常用的功能之一。每当构建一个镜像时,都是在使用 Docker Build。
Docker Build 不仅是用于构建镜像的命令,也不仅仅是关于打包代码的。它属于一个完整的生态系统,支持很多常用的工作流工具,以及更复杂和高级场景。
Docker Build架构 Docker Build是一个client-server架构。Buildx是客户端,Builder是服务端。在Docker Engine 23.0和Docker Desktop 4.19之后,执行Docker build命令,默认使用Buildx客户端;在之前,需要显式的调用Docker Buildx Build才会使用Buildx工具。
Docker Build执行流程 BuildKit是执行构建工作的守护进程。
调用 docker build 命令后,由Buildx解析构建命令,然后向BuildKit发送构建请求。构建请求的内容包括:
Dockerfile构建参数导出选项缓存选项 BuildKit 解析构建请求并执行构建步骤。
在构建期间,Buildx监视构建状态并将进度打印到终端。如果构建需要来自客户端的资源,例如本地文件或构建密钥,则 BuildKit 会从 Buildx 请求所需的资源。这是 BuildKit 相对于它替代的传统构建器更高效的一种方式。与之相比,BuildKit 仅在需要时请求构建所需的资源。传统构建器则始终会复制本地文件系统。BuildKit 可以从 Buildx 请求的资源包括:
本地文件系统构建上下文构建密钥SSH 套接字注册表认证令牌。 一个构建流程示例:
怎么使用Docker Build 构建的核心是Dockerfile。
Docker 通过读取 Dockerfile 中的指令来构建镜像。Dockerfile是一个文本文件,通过一系列指令将应用程序组装成容器镜像。
下是最常见的指令类型:
FROM 指定基础镜像。RUN 在当前镜像的顶部新建一个层并执行任何命令,然后提交结果。RUN 还有一种 shell 形式用于运行命令。WORKDIR 为随后的 RUN、CMD、ENTRYPOINT、COPY 和 ADD 指令设置工作目录。COPY 从 复制新文件或目录,并将它们添加到容器的文件系统中,路径为 。CMD 定义由本镜像启动容器时运行的默认程序。每个 Dockerfile 只有一个 CMD语句,当存在多个 CMD 语句时,只有最后一个 CMD 语句会被使用.
SocketD是一个基于Socket的通信框架,支持单链接双向RPC模式。在实现单链接双向RPC模式时,需要按照一定的协议进行通信,以下是一个简单的实现示例:
定义通信协议:首先,需要定义客户端和服务端之间的通信协议,例如使用JSON格式来进行数据传输。
客户端和服务端通信:客户端通过Socket连接到服务端,并发送请求数据,请求数据可以包含调用的方法名、参数等信息。
服务端接收请求:服务端监听Socket连接,并接收客户端发送的请求数据。
服务端处理请求:服务端根据接收到的请求数据,调用相应的方法,并返回执行结果。
客户端接收响应:客户端接收服务端返回的响应数据,并解析响应结果。
实现双向通信:为了实现双向通信,可以在客户端和服务端分别使用两个线程来处理请求和响应,使得客户端和服务端可以同时进行请求和响应的处理。
示例代码如下(使用Python的socket库):
服务端代码(server.py):
import socket
import json
def add(a, b):
return a + b
def sub(a, b):
return a - b
def handle_request(client_socket):
data = client_socket.recv(1024).decode()
request = json.loads(data)
method = request['method']
params = request['params']
if method == 'add':
result = add(*params)
elif method == 'sub':
result = sub(*params)
else:
result = 'Unknown method'
response = json.dumps({'result': result})
client_socket.send(response.encode())
client_socket.close()
def main():
server_socket = socket.
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
HTML快速入门 一、表单标签二、CSS入门1.CSS导入方式2.CSS选择器 三.get和post的区别四.JS入门1.数据类型和运算符2.Window对象3.事件绑定4.表单验证5.正则表达式 进入W3C官网可以更好的自我学习
W3CSchool官网
一、表单标签 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> </title> </head> <body> <form action="#" method="post"> <input type="hidden" name="id" id="123"> <!-- 这里使用Lable标签,是使点击文本也能被选中--> <label for="username"> 用户名:</label> <input type="text" name="username" id="username"><br> <label for="password">密码:</label> <input type="password" name="password" id="password"><br> 性别: <input type="radio" name="gender" value="1" id="male"><label for="male">男</label> <input type="radio" name="gender" value="0" id="female"><label for="female">女</label><br> 爱好: <input type="checkbox" name="hobby" value="1"> 旅游 <input type="checkbox" name="hobby" value="2"> 音乐 <input type="checkbox" name="hobby" value="3"> 电影 <br> 城市: <select name="
requests参数 params:在GET请求中,将参数添加到URL的查询字符串中。data:在POST请求中,将参数添加到请求体中。headers:设置HTTP请求的头部信息,如User-Agent、Content-Type等。cookies:设置请求的Cookies。auth:设置HTTP认证信息,如用户名和密码。timeout:设置请求超时时间。proxies:设置代理服务器。verify:是否验证服务器的SSL证书。allow_redirects:是否允许重定向。 发送GET请求 import requests ''' 发送GET请求,解决响应乱码问题 ''' response = requests.get("http://www.baidu.com/") print("原始的数据编码为:", response.encoding) print("设置前响应数据:", response.text) # 设置响应数据编码格式 # 响应数据乱码,设置编码 response.encoding = "utf-8" print("设置编码后数据编码为:", response.encoding) print("设置后响应数据:", response.text) 发送POST请求 提交form表单,参数为data
import requests login_url = "http://localhost/index.php?m=Home&c=User&a=do_login" login_data = { "username": "13641111112", "password": "123456", "verify_code": "8888" } response = requests.post(url=login_url, data=login_data) # 看响应 print(response.json()) 提交json数据,参数为json
import requests # 发送请求 login_url = "http://ihrm-java.itheima.net/api/sys/login" login_data = { "mobile": "13800000002", "password": "123456" } response = requests.post(url=login_url, json=login_data) # 查看响应 print(response.
packages/SystemUI/src/com/android/systemui/privacy/PrivacyConfig.kt
private const val DEFAULT_MIC_CAMERA = false 改成false就好了
GWO简介 Mirjalili 等人于2014年提出来的一种群智能优化算法。该算法受到了灰狼捕食猎物活动的启发而开发的一种优化搜索方法,它具有较强的收敛性能、参数少、易实现等特点。
社会等级分层:初始化种群,将适应度最好的三个个体标记为 α 、 β 、 σ \alpha、\beta、\sigma α、β、σ,剩下的狼群为 ω \omega ω,GWO优化过程中主要由每代种群中三个最好的解来指导完成。
位置更新计算 左边图中表示二维的向量及可能的区域,可以看出灰狼的位置根据中间猎物的位置 ( X ∗ , Y ∗ ) (X^*,Y^*) (X∗,Y∗)进行更新,通过调节 A → , C → \overrightarrow{A},\overrightarrow{C} A ,C 的值,可以到猎物周围不同的地方。
D → = ∣ C → ⋅ X → p ( t ) − X → ( t ) ∣ A → = 2 a → ⋅ r 1 → − α → C → = 2 ⋅ r 2 → X → ( t + 1 ) = X → p ( t ) − A → ⋅ D → \begin{aligned} &\overrightarrow{D}=\vert \overrightarrow{C}\cdot\overrightarrow{X}_p(t)-\overrightarrow{X}(t)\vert \\ &\overrightarrow{A}=2\overrightarrow{a}\cdot\overrightarrow{r_1}-\overrightarrow{\alpha}\\ &\overrightarrow{C}=2\cdot\overrightarrow{r_2}\\ &\overrightarrow{X}(t+1)=\overrightarrow{X}_p(t)-\overrightarrow{A}\cdot\overrightarrow{D} \end{aligned} D =∣C ⋅X p(t)−X (t)∣A =2a ⋅r1 −α C =2⋅r2 X (t+1)=X p(t)−A ⋅D
Apache Doris是一个分布式的列式存储系统,它的设计目标是提供大规模数据处理的可靠性和高性能。Doris采用了集群方式,通过将数据分布在多个机器上进行处理来提高性能,并提供了SQL查询接口方便用户使用。
StarRocks是一个分布式存储系统,它建立在Apache Hadoop之上,旨在为大型超级计算机提供结构化数据存储解决方案。StarRocks采用了列式存储模型,并利用Hadoop的分布式计算框架来管理数据和提供高性能的数据处理。
因此,Doris和StarRocks的主要区别在于:
底层架构不同:Doris是一个独立的分布式存储系统,而StarRocks是建立在Hadoop之上的。
存储模型不同:Doris使用列式存储模型,而StarRocks使用Hadoop中的HDFS文件系统来存储数据。
处理能力不同:Doris提供高性能的数据处理能力,而StarRocks利用Hadoop的分布式计算框架来处理数据。
介绍 游戏引擎是游戏开发中不可或缺的工具,它为开发者提供了构建游戏世界所需的各种功能和工具。本文将介绍游戏引擎的概念、使用方法以及一个完整的游戏项目示例。
游戏引擎的概念 游戏引擎是一种软件框架,它提供了游戏开发所需的各种功能和工具,包括图形渲染、物理模拟、碰撞检测、音频处理等。使用游戏引擎,开发者可以更快速、高效地构建游戏世界,并实现游戏的各种功能和效果。
常见的游戏引擎 Unity:Unity是目前最受欢迎的游戏引擎之一,它支持跨平台开发,并提供了强大的编辑器和工具。Unity适用于各种类型的游戏开发,并有一个庞大的社区和资源库。Unreal Engine:Unreal Engine是一款由Epic Games开发的游戏引擎,它具有出色的图形渲染和物理模拟能力。Unreal Engine适用于开发高度逼真的游戏,并提供了丰富的蓝图系统,使开发者可以在不编写代码的情况下实现复杂的游戏逻辑。Cocos2d-x:Cocos2d-x是一款开源的跨平台游戏引擎,适用于2D游戏开发。它使用C++语言编写,具有高性能和灵活的特点。Cocos2d-x还提供了JavaScript和Lua等脚本语言的支持,方便开发者进行快速原型开发。 游戏引擎的使用方法 1. 下载和安装游戏引擎 首先,你需要从游戏引擎的官方网站下载并安装游戏引擎。根据你的需求和平台选择相应的版本。
2. 创建项目 打开游戏引擎的编辑器,创建一个新的项目。在项目中,你可以添加场景、角色、动画等元素,并设置游戏的各种属性和逻辑。
3. 编写脚本 使用游戏引擎提供的脚本语言,如C#、C++、JavaScript等,编写游戏的逻辑代码。通过脚本,你可以控制角色的移动、对话、碰撞检测等行为。
4. 资源管理 游戏引擎提供了资源管理器,你可以将图像、音频、动画等资源导入到项目中,并在游戏中使用。
5. 编译和发布 完成游戏的开发后,你可以将游戏编译为可执行文件或打包为移动应用程序,并发布到各个平台上。
完整的游戏项目示例 下面是一个完整的游戏项目示例,使用Unity游戏引擎创建一个简单的2D平台游戏。
项目概述 这个游戏是一个经典的横向卷轴平台游戏,玩家需要控制角色跳跃和躲避障碍物,尽可能地到达终点。
游戏场景 游戏场景包含了玩家角色、障碍物、背景等元素。玩家可以通过键盘控制角色的移动和跳跃。
角色控制脚本 using UnityEngine; public class PlayerController : MonoBehaviour { public float speed = 5f; public float jumpForce = 5f; private Rigidbody2D rb; void Start() { rb = GetComponent<Rigidbody2D>(); } void Update() { float moveHorizontal = Input.GetAxis("Horizontal"); float moveVertical = Input.
以前用DEV C++这个编译器时,看过easyx 这个C++图形库,文档中有范例程序,是模拟星空的,觉得的不错,今天有空,把Crossin用python写的一个雪花模拟程序,修改了一下,效果和easyx的基本一模一样。
使用easyx的C++代码:
// 编译环境:Visual C++ 6.0~2022,EasyX_2023大暑版 // https://easyx.cn // #include <graphics.h> #include <time.h> #include <conio.h> #define MAXSTAR 200 // 星星总数 struct STAR { double x; int y; double step; int color; }; STAR star[MAXSTAR]; // 初始化星星 void InitStar(int i) { star[i].x = 0; star[i].y = rand() % 480; star[i].step = (rand() % 5000) / 1000.0 + 1; star[i].color = (int)(star[i].step * 255 / 6.0 + 0.5); // 速度越快,颜色越亮 star[i].
Python中sys 模块中的一个方法是stdout ,它使用其参数直接显示在控制台窗口上。
这些种类的输出可以是不同的,像一个简单的打印语句,一个表达式,或者一个输入提示。print() 方法,它有相同的行为,首先转换为sys.stdout() 方法,然后在控制台显示结果。
sys.stdout 方法的语法 sys.stdout 参数
不涉及任何参数。我们使用sys.stdout 作为输出文件对象。
返回值
该方法不返回任何值,只在控制台直接显示输出。
示例:在Python中使用sys.stdout 方法 # import the sys module to use methods import sys sys.stdout.write('This is my first line') sys.stdout.write('This is my second line') 输出:
This is my first line This is my second line 它将返回sys.stdout.write() 方法中传递的参数并在屏幕上显示。
示例:sys.stdout.write() 与print() 方法 import sys # print shows new line at the end print("First line ") print("Second line ") # displays output directly on console without space or newline sys.
题解 | #牛群的能量#
题目考察的知识点动态规划题目解答方法的文字分析用 f(i)代表以第 i个数结尾的「和最大子群能量值之和」,设数组的长度为n,则本题的答案时从0到n-1这n个f(
题解 | #牛牛的名字游戏#
题目考察的知识点字符串题目解答方法的文字分析用jdk自带的split方法,将字符串变成单词数组,取最后一个单词并返回它的长度。本题解析所用的编程语言java完整
题解 | #牛群消息传递#
题目考察的知识点字符串题目解答方法的文字分析用java自带的方法trim(),将字符串除去开头和末尾的空白字符,然后用正则匹配连续的空白字符作为分隔符分割,将字
题解 | #牛群的信息传递#
题目考察的知识点字符串题目解答方法的文字分析遍历keyword的第一个字符在字符串message中可能出现的位置,每次截取和keyword.length相同的长
题解 | #质数因子#
import mathdef func(num): result = "" prime = 2 while prime &
题解 | #回文昵称#
题目考察的知识点字符串,双指针题目解答方法的文字分析因为字符串要忽略大小写,所以先将字符串大写字母全部转换成小写字母。然后用left,right指针分别指向字符
江南大学的食品工程全国第一
江南大学的食品工程全国第一
异地+卷王,不知道有没有未来
多模态大模型寻求partner
当你穿越到道诡异仙的世界,如何利用密码学知识区分幻想和现实?
《道诡异仙》是一部流行的网络小说。 其中,剧情讲述了男主角李火旺穿越到诡异世界,但意识时不时会回到原来的现代社会中。两个世界时不时交错,男主角陷入到了混乱当中,
虚幻中的角色动画都是基于 骨骼网格体 (Skeletal Mesh)实现,换言之,动画是跟骨骼网格体绑定的。如果有两个骨骼网格体,各自有一套角色动画,那么就可以通过重定向(Retargeting)将两个骨骼网格体做绑定(Rig),从而迁移动画,实现在不同网格体间的角色动画的复用。
(本篇没有 C++ 代码,只是不讲这个,好像没法玩下去。毕竟如果下载别人角色或动画,然后不知道怎么用到自己的项目上,那等于没用)
使用模板 UE4 动画重定向到 UE4 UE5 带有 Mannequin 的 IK Rig,可以不需要手动绑定,手动绑定的方法见下面。
使用第三人称模板就自带了 Mannequin 的 IK Rig,就不需要手动进行绑定了。同时也提供了两个 Retargeter,分为处理从 UE5 Manny 角色到 UE4 的 Mannequin 之间的重定向,以及 UE4 的 Mannequin 到 UE5 的 Manny 角色之间的重定向。
此时我们 UE5 第三人称模板里只有一个 Mannequin 动画:
假设现在从商店导入了一个 Mannequin 动画包(选 5.0 即可):
由于动画资产一般都自洽(自带 Mesh):
所以这个时候发现我们自己的 Mannequin 还是只有一个动画。当我们知道这两个 Mannequin 都是一样的。那么只需要拷贝一份 IK,将预览的骨骼改成 AnimStarterPack 中的骨骼。这样就算绑定好了。
具体步骤:
复制 IK_UE4_Mannequin,重新命名;将 Preview Skeletal Mesh 修改成 AnimStarterPack 的 Mesh;新建一个 RTG 资产,选择这两个 IK 资产进行重定向即可。由于是要将下载的动画重定向到本地项目,那么源 Source 就应该是 AnimStarterPack 的 IK 和 Mesh,Target 是本地的 IK 和 Mesh;导出需要的动画,可以添加前缀、后缀等等。 UE4 动画重定向到 UE5 UE4 的 Mannequin 重定向到 Manny 和 Metahuman 只需要用自带模板即可。直接复制自带的 RTG,即 RTG_UE4Manny_UE5Manny。然后将 Source IK 修改成需要动画对应的 IK 即可。但会发现一个问题,就是手部有明显问题。
参考书籍:数值分析 第五版 李庆杨 王能超 易大义编 第7章 非线性方程与方程组的数值解法
文章声明:如有发现错误,欢迎批评指正
文章目录 迭代法求解 x e x − 1 = 0 xe^x-1=0 xex−1=0牛顿法求解 x e x − 1 = 0 xe^x-1=0 xex−1=0简化牛顿法求解 x e x − 1 = 0 xe^x-1=0 xex−1=0 7.1方程求根与二分法:太简单了(程序设计竞赛这些都是基本)。直接跳过。注意一下一些概念。 7.2不动点迭代法及其收敛性:7.2.1不动点与不动点迭代法: f ( x ) = 0 f(x)=0 f(x)=0恒等变为 x = φ ( x ) x=\varphi(x) x=φ(x)。用迭代方程 x k + 1 = φ ( x k ) x_{k+1}=\varphi(x_k) xk+1=φ(xk), x ( 0 ) x_{(0)} x(0)随便选。如 lim k → ∞ x k = x ∗ \lim\limits_{k\rightarrow\infty}x_k=x^* k→∞limxk=x∗,则称迭代方程收敛;反之,发散。7.
系列文章目录 个人简介:机电专业在读研究生,CSDN内容合伙人,博主个人首页
Python入门专栏:《Python入门》欢迎阅读,一起进步!🌟🌟🌟
码字不易,如果觉得文章不错或能帮助到你学习,可以点赞👍收藏📁评论📒+关注哦!😊😊😊
文章目录 系列文章目录导语函数函数的创建与调用参数传递位置参数与关键字参数为参数设置默认值可变参数 返回值变量的作用域匿名函数常见Python内置函数 类与对象面向对象概述类的定义与使用`__init__()` 方法访问限制 属性创建用于计算的属性为属性添加安全保护机制 继承 结语 导语 欢迎来到 Python 零基础入门系列的第九篇!前面的文章中,已经介绍了 Python 的基本语法、控制流程和数据类型等内容。这一篇博客将继续探索 Python 编程的核心概念——函数,类和对象。
函数 Python 编程中,函数的应用非常广泛。在前面我们已经多次接触过函数。如,用于输出的 print() 函数、用于输入的 input() 函数,以及用于生成一系列整数的 range() 函数。这些都是 Python 内置的标准函数,可以直接使用。除了可以直接使用的标准函数外,Python 还支持自定义函数。即通过将一段有规律的、 重复的代码定义为函数,来达到一次编写多次调用的目的。使用函数可以提高代码的重复利用率。
函数的创建与调用 在 Python 中,def 关键字用来定义函数。语法如下:
def fuctionname(parameter1, parameter2, ...): ['''comment'''] [fuctionbody] ‘comments’:可选参数,表示为函数指定注释,注释的内容通常是说明该函数的功能、要传递的参数的作用等。如果指定了 comments 参数,那么在调用函数时,输入函数名称及左侧的小括号时,就会显示该函数的帮助信息。这些帮助信息就是通过定义的注释提供的。
函数的定义由函数名、参数列表和函数体组成。函数名应该是一个描述性的名字,体现函数的作用。参数列表也可以不指定参数,不指定则表示该函数没有参数。在调用时,也不指定参数。
如果想定义一个什么也不做的空函数,可以使用 pass 语句作为占位符。在 Python3.x 版本中,允许在可以使用表达式的任何地方使用 ... (3 个连续的点号)来省略代码,由于省略号自身什么都不做,因此,可以当作是 pass 语句的一种替代方案。
调用函数也就是执行函数。调用函数时,使用函数名后加上括号来调用。在括号内,传递函数需要的参数。参数的数量和类型应该与函数定义中的参数列表一致。
参数传递 位置参数与关键字参数 函数可以接受参数,参数是函数的输入。Python 中有两种类型的参数:位置参数和关键字参数。位置参数是必须按照参数在函数定义中的顺序传递的;而关键字参数则是通过指定参数名来传递的,需要将参数名写对。
def greet(name, greeting): return f"{greeting}, {name}!" # 位置参数传递 print(greet("
VSCode 调试 C++ 主要就是 .vscode 中的 launch.json 和 tasks.json 的配置。
launch.json 可以通过 vscode 界面 ——》左侧调试功能按钮——》创建 launch.json ——》C++(GDB/LLDB)生成。
其中 launch.json 默认配置如下,主要配置项说明:
name:启动项的名字program:指向最终生成的可执行文件的路径args:执行时的输入参数stopAtEntry:自动在 main 函数时停止 { "version": "0.2.0", "configurations": [ { "name": "C/C++: g++ build and debug active file", "type": "cppdbg", "request": "launch", "program": "${fileDirname}/${fileBasenameNoExtension}", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", "setupCommands": [ { "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true } ], "
目录
一. 前言
二. STUN报文格式
STUN Header
RFC3489
RFC5389
STUN Message Body
RFC3489
RFC5389
三. WebRTC对STUN协议的支持
四. STUN工作流程
1. 使用STUN获取NAT映射后的地址
五. 参考资料
一. 前言 现实网络环境中绝大多数主机都是处于 NAT 之后,对于两个处于同一内网环境的主机,它们只要知道对端的内网地址就能进行通信,而对于不在同一内网的主机,如果它们想通信,要么借助带有公网地址的主机转发,要么通过一定的手段进行 NAT 穿越。
STUN 协议是用来 NAT 穿越的工具,它允许位于 NAT 之后的主机查找到自己 NAT 映射后的公网地址,需要通信的双方交换映射后的公网地址再进行连通性检测。
STUN 最先在 RFC3489 中定义,英文全称是 Simple Traversal of UDP Through NAT,即用 UDP 进行 NAT 穿越,而新的 RFC5389 把 STUN 定义为 Session Traversal Utilities for NAT,即 NAT 会话传输工具,RFC3489 与 RFC5389 相比,最大的区别是后者支持 TCP 穿越。
STUN 协议是一个 C/S 模型的协议,即一端发送请求,另一端进行响应,此外还有指示类型的消息,一端发送指示消息后,另一端不必响应。
2021年5月,USB-IF 协会发布了全新的USB PD3.1规范,该规范将快充功率上限从100 W提升至240W(支持Extended Power Range,简称EPR)。充电功率的提升也让USB PD的应用从手机、笔记本电脑,扩展到便携式设备、物联网设备、智能家居、通信和安防设备、汽车和医疗等领域。
面对更多的应用场景,市场对于PD协议芯片的要求也越来越高。乐得瑞针对设备取电场景推出了LDR6328Q多协议取电芯片,支持PD+QC+AFC协议,可以从PD/QC/AFC协议适配器上取到需要电压,并且可以自行配置诱骗电压,有9V,12V,15V,20V可以选。
随着Type-C接口的普及,各大设备厂商都在积极推动采用Type-C接口供电,LDR6328Q可以从适配器取到需要的电压给后端用电器使用,比如某品牌蓝牙音箱更新为Type-C接口12V快充,充电效率比传统的5V充电快了很多倍,体验感比之前充电几小时好多了。
LDR6328封装小巧,价格低廉,非常适合消费类产品,采用Type-C接口供电,厂商也能少配一个专用适配器,节约了不少成本,用户也更方便,携带设备出门只需带一个适配器即可,不用再像从前一样准备多种不同适配器。
遇到报错不要慌,看看是什么报错,看看绿色字的提示,照着修改之后,果然能解决~!!
找到绿色字体需要添加头文件的cpp文件,逐一添加头文件,继续根据步骤安装即可
git clone https://github.com/rmsalinas/DBow3.git #下载源文件 cd DBoW3 #进入源文件夹 mkdir build #新建一个编译目标文件夹 cd build #将build作为make工作路径 cmake -DUSE_CONTRIB=ON .. #编译上一级目录,如果您提前安装好了contrib_modules,则使用cmake选项-DUSE_CONTRIB=ON使能SURF,否则直接运行cmake .. make sudo make install #安装DBoW3
是对是错也好 不必说了
是怨是爱也好 不须揭晓
何事更重要 比两心的需要
柔情蜜意怎么可缺少
——《说不出再见》谭咏麟
文章目录 前言一、练习题题目二、创建测试数据(一)创建测试表(二)插入测试数据 三、思路四、解答(一)详细代码(二)结果展示 五、知识拓展——使用 grouping 运算符计算小计合计值(一)rollup1. 详细代码2. 结果展示3. 代码优化 总结 前言 昨天晚上在回答一个小伙伴的SQL问题时,发现这个问题很有代表性,考察到多个SQL语法和逻辑思维,在此分享给大家,可以作为SQL练习题使用,欢迎一起讨论多种解题思路。
一、练习题题目 现有一个班级学生各学科成绩表,求平均分低于80分的班级学生各科成绩并合计学生总分(要求合计作为行位于该同学各学科之下)
最终结果类似下面截图,可以看作每个班每个学生为一组,先展示其各学科成绩,再生成合计行。
二、创建测试数据 (一)创建测试表 创建表 test_20230724,包含如下字段: class(班级),name(学生姓名),course(学科),score(分数)。
create table test_20230724 ( class varchar(50) ,name varchar(50) ,course varchar(50) ,score INT ); (二)插入测试数据 插入两个班,四位同学的成绩。
insert into test_20230724 values ('1','张三','语文',80), ('1','李四','数学',95), ('1','张三','数学',90), ('1','李四','英语',80), ('1','王五','数学',70), ('2','小明','语文',80), ('2','小明','数学',70); 三、思路 将该问题拆分,分步处理
第一步,求出平均分低于80分的班级
第二步,平均分低于80分的班级中,求出班级学生各科成绩
第三步,平均分低于80分的班级中,按学生合计总分
第四步,合并第二步和第三步数据
四、解答 (一)详细代码 SELECT class ,name ,course ,score FROM test_20230724 WHERE class IN ( SELECT class FROM test_20230724 GROUP BY class HAVING AVG(score) < 80 ) UNION ALL SELECT class ,name ,'合计' AS course ,SUM(score) AS score FROM test_20230724 WHERE class in ( SELECT class FROM test_20230724 GROUP BY class HAVING AVG(score) < 80 ) GROUP BY class ,name (二)结果展示 五、知识拓展——使用 grouping 运算符计算小计合计值 grouping 运算符包含以下3种:rollup、cube、grouping sets
1 词云简介 词云也叫文字云,是一种可视化的结果呈现,常用在爬虫数据分析中,原理就是统计文本中高频出现的词,过滤掉某些干扰词,将结果生成一张图片,直观的获取数据的重点信息。今天,我们一起来学习一下Python生成词云的常用库「wordcloud」。
wordcloud是第三方库,需要提前下载安装。
安装: pip install wordcloud
wordcloud 对象有很多参数设定,设定不同的参数,可以绘制不同形状、颜色和尺寸的词云图。
2 WordCloud对象常用参数 参数说明font_path设置字体,指定字体文件的路径width生成图片宽度,默认400像素height生成图片高度,默认200像素mask词云形状,默认使用矩形min_font_size词云中最小的字体字号,默认4号font_step字号步进间隔,默认1max_font_size词云中最大的字体字号,默认根据高度自动调节max_words词云显示的最大词数,默认200stopwords设置停用词(需要屏蔽的词),停用词不在词云中显示,默认使用内置的STOPWORDSbackground_color图片背景颜色,默认黑色 3 WordCloud常用方法 方法功能generate(text)加载词云文本to_file(filename)输出词云文件 wordcloud默认是为了英文文本来做词云的,如果需要制作中文文本词云,就需要先对中文进行分词。这里就需要用到中文分词库「jieba」。
4 jieba 分词库 jieba 是优秀的中文分词库,需要安装。它的原理是利用一个中文词库,确定中文字符之间的关联概率,汉字间概率大的组成词组,形成分词结果,除了分词,还可以添加自定义词组。
安装:pip install jieba
jieba有三种分词模式,这里我们只学习它的精确模式,把文本精确地切分开,不存在冗余单词。
使用jieba.lcut(s),返回列表型分词结果。当然,也可以使用jieba.add_word(w)向jieba库中增加词语。
5 使用wordcloud生成词云的步骤 读取文件,分词整理,生成词云文本配置wordcloud对象参数,加载词云文本计算词频,输出词云文件 6 词云案例 --- 爬取最近很火的一部电影《芭比》的影评数据,生成词云图。 1)生成文本文件 获取豆瓣电影网站10页短评数据,保存到文本中。
代码如下:
import requests from lxml import etree import time import random # 通过观察url翻页的规律,使用for循环得到10个链接,保存到urls列表中 urls = ['https://movie.douban.com/subject/4058939/comments?start={}&limit=20&status=P&sort=new_score'.format(str(i)) for i in range(0, 200, 20)] # print(urls) headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.
什么是Bitmap 操作String数据类型的key所存储的字符串指定偏移量上的位,返回原位置的值
优点:
节省空间通过一个bit位来表示某个元素对应的值或者状态,其中key就是对应元素的值。实际上8个bit可以组成一个Byte,所以是及其节省空间的效率高setbit 和 getbit的时间复杂度都是O(1),其他位运算效率也高 缺点:
不在意业务数据本质上位只有0和1的区别,所以用位做业务数据记录,就不需要在意value的值、 位图不是特殊的数据结构,它的内容其实就是普通字符串,也就是 byte 数组。我们可以使用普通的 get/set直接获取和设置整个位图的内容,也可以使用位图操作 getbit/setbit 等将 byte 数组看成 [位数组] 来处理。
用法 setbit 说明:给一个指定key的值第offset位赋值位value
参数:key offset value: bool or int(1 or 0)
返回值:LONG:0 or 1
127.0.0.1:6379> setbit bit 1 1
(integer) 0
getbit 说明:返回一个指定key的二进制信息
参数:key offset
返回值:LONG:0 or 1
127.0.0.1:6379> getbit bit 1
(integer) 1
bitcount 说明:返回一个指定key中位的值为1的个数
参数:key offset start end
返回值:LONG:0 or 1
127.0.0.1:6379> bitcount bit 0 -1
(integer) 2
bitfield bitfield 有三个子指令,分别是get/set/incrby,它们都可以对指定位片段进行读写,但是最多只能处理64个连续对位,如果超过64位,就得使用多个子指令,bitfield 可以一次执行多个子指令
企业软件研发痛点 在理想的工作场景中,产品经理、开发人员、QA 人员、IT 运维人员和信息安全人员相互合作,共同努力实现公司的目标。他们建立了从产品计划到功能上线的端到端快速服务交付流水线,每天执行几十次、数百次甚至上千次代码部署,同时保证系统的稳定性、可靠性、可用性和安全性。跨职能团队严谨地验证他们的假设,不仅关注用户特性的实现,还积极保障交付能够顺畅、频繁地通过整个交付价值链。QA 人员、IT 运维人员和信息安全人员共同投身于团队文化建设,致力于创造能使开发人员效率更高、产能更大的工作环境。在这个场景中,小团队能够快速独立地开发、测试和部署代码,并且可以快速、安全、可靠地向客户交付价值。
然而在现实中,服务和产品总是不尽如人意,团队的潜力无法得到正常发挥。开发和IT运维是对立的,测试和信息安全活动总是在项目晚期才进行。产品和服务交付中的关键活动需要手动操作和交接,导致进度拖延和质量问题频发。不仅影响了工作效率和业绩,也让IT员工感到无力改变流程及其结果。
为了解决这些问题,我们需要改变工作方式,DevOps正是能够帮助我们实现这一目标的一种软件工程文化和实践。DevOps旨在统一软件开发和运维,在软件工程的所有步骤中,提倡自动化和监控,助力实现更可靠的发布,缩短开发周期,提高部署频率,与业务目标保持紧密一致。
WorkMap研发管理平台 WorkMap研发管理平台,致力于解决软件产品生命周期遇到的问题,基于多年的DevOps实践经验,打造一站式DevOps平台及技术管理解决方案,助力企业高质量、低成本、无风险的快速交付客户价值。
平台集成了项目管理、代码管理、制品管理、持续部署、测试中心、监控告警、知识管理功能,覆盖软件开发全周期,为企业提供一站式标准化产品,通过自动化“软件交付”的流程,使软件的构建、测试和发布变得更加快捷、频繁和可靠。
项目管理模块提供看板、燃尽图等可视化工具,直观的查看每个项目的进展情况;需求、任务、缺陷池,打通与研发团队、质量团队的工作交接。
代码管理模块支持多种分支开发模型,适配不同团队的不同协作方式。同时,提供代码扫描、bug扫描等自动化工具,保障代码质量。
制品管理模块内置多种制品库,maven仓库、npm仓库、镜像仓库等,动态配置,一键构建,一键发布。
持续部署模块,内置配置管理工具,可以一键部署到云平台、虚拟机、物理机等不同环境。提供灰度部署、蓝绿部署、平滑更新等安全部署解决方案。
测试中心模块,提供压力测试、单元测试、功能测试等自动化测试工具,测试计划反复执行,生成标准化测试报告。
监控告警模块,一键安装,自动采集监控数据,生成标准化看板,研发人员可自助添加和管理告警,减少运维压力,实现服务研发上线运营闭环。
知识管理模块,可关联到软件开发流程的各个阶段,跟踪记录需求、代码、构建、部署、测试、发布、运维各个阶段的知识和反馈,建立持续学习与实验的企业文化。
自研流程管理引擎,提供标准化流程,支持自定义流程,打通从迭代任务-> 代码 -> 构建 -> 部署 -> 测试 -> 发布的全流程,实现研发流程标准化、自动化、可视化,同时,通过权限控制、实时通知、操作审计,实现权责划分,降低沟通成本,加速部门协作。
效能分析模块,收集软件开发全流程数据,通过可视化看板、数据报表,面向管理赋能,直击痛点,提高短板。
亮点 一体化平台 覆盖软件开发全流程,将开发、测试、运维、管理能力服务化,提供高度自动化平台,可无缝衔接企业发展的不同阶段。
灵活性 采用插件式架构,可对接各种主流DevOps工具,支持跨云、跨集群,支持各种主流技术选型,支持不同形式的研发流程。
加速交付 支持精益创业理念,旨在消除价值流中的困境和浪费,通过标准化、自动化流程,减少沟通成本,促进部门协作,加速价值流动。
数据打通 全流程数据,打通从需求到交付的软件开发全周期数据,提供多方位研发效能度量。
面向管理 实现管理要素中的组织、计划、控制,实时反馈,赋能决策。
关于WorkMap
WorkMap研发管理平台,一站式DevOps平台,助力企业改进软件产品端到端的交付方式,提升部门间协作效率,以安全可靠的方式快速实现商业价值。
目前提供免费版供下载使用,也可体验在线试用版,更加详细的内容,请参阅官网;
官方交流群,此群可交流WorkMap平台使用心得、微服务、云原生、敏捷等相关理论实践心得,大家可以加群讨论交流。
WorkMap官方交流1群(已满);
WorkMap官方交流2群(可加);【微信号发至邮箱service@ttransition.com,运营同事拉您入官方交流群】
文章来源:WorkMap技术博客-DevOps理论
说到devops,要从盘古开天辟地开始说起。软件工程这一学科的发展开始说起。
软件工程 软件工程,顾名思义,是一门研究用工程化方法,快速、高质量的生产软件的学科。这一学科出现于1968年,诞生的背景,是落后的软件生产方式无法满足迅速增长的计算机软件需求,导致软件开发与维护过程中出现一系列严重问题。人们试图借鉴建筑领域的工程方法论来解决这一问题。
瀑布模型 最早提出来的解决方案,是瀑布软件开发方法。Dr. Winston W. Rovce于1970年发表了文章“Managing the development of large software systems”,文中首次提出了瀑布软件开发模型。瀑布模型将软件开发过程拆分成多个阶段,需求分析,原型设计,开发,测试,部署运行,这些概念模型现在也还在使用。区别只是,当时的软件通常都是大型商业软件,交付周期长,通常以年为单位。并且是一次交付,长期使用。
敏捷开发 到了20世纪80年代,微型计算机开始普及。人们对轻量级软件的需求迎来爆发,瀑布模型的开始暴露出各种问题。为了应对问题,这个时期涌现了大量的新软件开发方法,比如scrum,极限编程。2001年,17位软件大师在美国犹他州的“雪鸟镇”,总结了这些轻量级软件的开发方法,发表了“敏捷宣言”,提出了敏捷开发应该遵守的十二原则,凡是符合这些原则的开发方法,都是敏捷开发。所以,敏捷开发是一簇软件开发方法。
敏捷开发提出了迭代的概念,一个软件交付计划,划分成多个迭代,每次迭代都是一个可以运行的软件产品。此时软件发布的时间间隔仍旧较长,通常是数月,甚至是一年。主要矛盾是业务人员和研发团队之间,需求变更和研发效率的矛盾。构建和发布工作,在整个发布周期中占用的时间和成本较小,部署和运维工作还不是突出的矛盾。
持续交付 随着软件商业环境的进一步变化,人们开始提高软件的迭代速率。这时,测试和部署成为软件开发过程中困难且耗时的阶段。2006年,Jez Humble,Chris Read和Dan North共同发表了文章”The Deployment Production Line“。文中首次提出”部署生产线“模式:……通过多阶段的自动化工作流程,测试和部署过程可以完全自动化。利用这种”部署生产线“,可以将已验证的代码快速部署到生成环境中,并且一旦发生问题,可以轻松的回退到以前的版本。
这就对自动化测试和自动化运维提出了更高的要求。于是人们考虑将敏捷应用于测试和运维领域。
DevOps起源 2008年8月的敏捷大会上,提出了一个临时话题“敏捷基础设施”,比利时的IT咨询师Patric Debois开始思考“将敏捷应用于运维领域”。2009年,他在比利时组织了“DevOpsDays"社区,正式启用了DevOps这个术语。它的原始定义是,DevOps是运维工程师和开发工程师参与整个服务生命周期(从设计开发到生产支持)的一组实践。
DevOps的发展 2011年出版的《精益创业》,核心思想是,开发新产品时,先做出一个简单的原型——最小化可行产品(MVP),得到用户真实反馈后,从反馈中学习,再快速迭代,持续修正,使价值流动起来。Flickr网站将其应用到互联网产品研发管理中,形成双环模型:
该模型强调业务与IT间的快速闭环,以”精益思想“为指导,识别和消除一切浪费,帮助企业以可持续方式,高质量、低成本、无风险的快速交付客户价值。
在这种研发管理模式的转变下,DevOps的含义越来越广泛。从涉及的角色来看,DevOps将敏捷开发涉及的范围扩大到产品需求方,软件研发团队(开发和测试),运维工程师。DevOps工具也变得越来越多。目前,业界对DevOps并没有统一的标准定义。每一位从业者、每一个企业都有自己理解的DevOps。
DevOps并不是一个标准,一种模式或一套固定方法,而是一种IT组织管理的发展趋势。目的是打破IT部门的隔阂,改变IT组织内部的原有合作模式,从而促进业务迭代速度。
DevOps的未来 2022年7月,软件工程师兼 DevOps 评论员 Sid Palas 在推特上写道,“DevOps 已死,平台工程才是未来。”他的核心观点是:开发者不想跟基础设施打交道,企业在发展过程中又需要控制自己的基础设施。只有平台工程,能将这两个相互矛盾的命题统一起来。
按照“平台工程”社区主要贡献者和 Humanitec 的产品负责人 Luca Galante 的说法,平台工程是一门设计和构建工具链与工作流的学科。这些工具链和工作流可以为云原生时代的软件工程组织提供自助服务功能。平台工程师提供集成化产品,通常称为“内部开发平台(Internal Developer Platform)”,可以涵盖应用程序整个生命周期的所有操作需求。
与其说DevOps已死,不如说是”涅槃重生“,新的DevOps形态,就是能够快速集成各种DevOps工具链,使价值流动起来,促进企业快速持续交付的DevOps平台。
目录
一、java.io.File
1.读取文件属性
2.创建文件
3.删除文件
4.创建一个目录
5.创建多级目录
6.删除目录
7.获取一个目录的所有子项
8.过滤一个目录中的部分子项
二、java.io.FileInputStream和java.io.FileOutputStream
1.FileInputStream读文件
2.FileOutputStream写文件
3.FileInputStream和FileOutputStream拷贝文件
一、java.io.File java.io.File类用于描述文件系统中的一个文件或目录 该类可以:
1、访问文件或目录的属性信息2、访问一个目录中的所有子项3、操作文件或目录(创建、删除) 该类不可以:
访问文件的具体内容 开发时注意不同操作系统的路径的表示方法的差异(如'/'或'\'),使用File.separator可以屏蔽不同操作系统的路径的差异。
1.读取文件属性 import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; public class FileDemo1 { public static void main(String[] args) { /* * 尽量不写绝对路径。 * 常用的是相对路径: * 1、相对于项目目录(当前目录) * 2、相对于类加载目录(实际开发更常用) */ File file = new File("." + File.separator + "test.txt"); //分隔符 System.out.println(file); /* * 获取当前文件的属性信息 */ //获取文件名(不包括文件路径) String name = file.getName(); System.out.println("文件名:"+name); //获取文件大小(字节) long length = file.
一、为什么要用到深拷贝? 在Vue中,深拷贝通常用于处理需要复制并独立管理的数据,以确保数据的改变不会影响到原始数据。以下是一些示例说明Vue中为什么要使用深拷贝:
1、避免引起共享问题:
在Vue中,组件之间经常会使用对象或数组作为数据的传递方式。如果将一个对象或数组直接赋值给另一个变量,那么他们之间将共享相同的引用。这就意味着,当你修改其中一个变量时,另一个变量也会相应的改变。为了避免这种引用共享的问题,我们可以使用深拷贝来复制数据的副本。
data() { return { originalData: { name: 'Alice', age: 25 } }; }, created() { // 使用深拷贝复制originalData this.copiedData = JSON.parse(JSON.stringify(this.originalData)); // 修改copiedData的值,不会影响originalData this.copiedData.age = 30; console.log(this.originalData.age); // 输出: 25 console.log(this.copiedData.age); // 输出: 30 } 2、防止突变问题:
当在Vue中使用响应式数据时,直接修改原始数据可能会引发一些问题。比如,在计算属性或监听器中修改原始数据时,Vue可能无法正确地跟踪数据的变化,导致视图不会及时更新。通过使用深拷贝来创建数据的副本,可以避免这种冲突变的问题。
data() { return { originalArray: [1, 2, 3] }; }, computed: { copiedArray() { // 使用深拷贝复制originalArray return JSON.parse(JSON.stringify(this.originalArray)); } }, mounted() { // 修改copiedArray的值,不会影响originalArray this.copiedArray.push(4); console.log(this.originalArray); // 输出: [1, 2, 3] console.
前言 下面由我精心整理的关于github项目资源搜索的一些方法,这些方法可以帮助你更快更精确的搜寻到你需要的符合你要求的项目。
写文章不易,如果这一篇问文章对你有帮助,求点赞求收藏~
好,下面我们直接进入正题——>
首先我们可以先了解一下一个项目的特征,以下面的项目为例:
一、普通关键词搜索 这个其实没什么好说的,就是直接输入关键词来实现项目的寻找,通过页面内筛选的方式来匹配寻找项目,好处是直接输入关键词省事,但如果你需要的是符合具体要求的项目,那么直接使用关键词搜索无异于大海捞针,所以重点看我下面的高级搜索。
二、高级条件搜索 这种主要是通过在搜索框中添加限定词来寻找,常用的的各种限制词语法如下:
搜索过滤的要素搜索栏语法按照编程语言搜索language:xxx按照项目(仓库名称)搜索in:name xxx按照项目(仓库)描述搜索in:description xxx按照README文件描述搜索in:readme xxx按照star数限制搜索stars:>n按照fork数限制搜索forks:>n按照更新时间限制(时间晚于)搜索(YYYY-MM-DD表示年月日)pushed:>YYYY-MM-DD按照某个人的某个项目限制搜索repo:owner/name搜索用户名下的所有项目(仓库)或某个项目(仓库)——用户名后加项目名称org:username搜索某个组织名下的项目(仓库)org:orgname按照关注者数量搜索Java followers:>=n 匹配有n个或更多关注者提及文字 "Java" 的仓库 上面这些是一些常用的Github的高级搜索语法,具体的可以查看官方文档:https://docs.github.com/zh/search-github/github-code-search/understanding-github-code-search-syntax
下面是具体的搜索演示,比如我们希望找到一个仓库是在2023-06-01之后更新过的且stars数大于10000的用Java编写的商城类项目,结合上述语法我们可以输入:
商城 in:readme stars:>10000 language:Java pushed:>2023-06-01 最终搜索到的结果如下,精准的筛选出了三个符合要求的项目:
除了上面我写的限定条件,你还可以根据自己的需求参照上面的语法继续添加条件,条件越多,能搜到的项目越精准。
三、通过排行榜寻找项目 下面的排行榜是根据star来排列的,这种方式可以帮助你找到优质的项目,当然如果要找一些符合自己要求的,还是推荐使用上面的高级搜索
具体网址:https://www.githubs.cn/top/Jav
一、先了解I2C协议 由时钟线SCL和数据线SDA构成的通信线路,利用上拉电阻将它们拉成高电平(表示总线空闲) I2C总线可以有多个从设备,且每个从设备都有一个唯一的7bit地址物理识别,因为I2C地址全0为广播地址,所以I2C总线理论上最多能带2^7-1=127个从设备
(I2C:半双工通信的同步串行通信协议,采用电平信号,数据传输采用大端方式MSB,先发高位数据)
I2C总线通信时序:
I2C协议的起始信号(start):当SCL保持高电平时,SDA出现一个下降沿,产生起始位
I2C协议的停止信号(stop):当SCL保持高电平时,SDA出现一个上升沿,产生停止位
(停止通信后,总线空闲,处于高电平)
主设备向从设备发送从设备地址信号,在收到从设备的应答信号后通讯连接才建立成功
若未收到应答则表示寻址失败。
希望继续,则给出“应答(ACK)”信号,即SDA为低电平
不希望继续,则给出“非应答(NACK)”信号,即SDA为高电平
(建立通信后才开始传输数据位)
(读写方向位:RW,0为写操作,1为读操作)
主机发送数据流程:
1、主机在检测到总线为空闲时,发送一个启动信号"S",开始一次通信的开始
2、主机接着发送一个从设备地址,它由7bit物理地址和1bit读写控制位R/W组成(此时RW=0)(发送的地址有7位的物理地址和1位的读写方向号)
3、相对应的从机收到命令字节后向主机回馈应答信号ACK(ACK=D)
4、主机收到从机的应答信号后开始发送第一个字节的数据;
5、从机收到数据后返回一个应答信号ACK;
6、主机收到应答信号后再发送下一个数据字节;
7、主机发完最后一个字节并收到ACK后,向从机发送一个停止信号P结束本次通信并释放总线;
8、从机收到p信号后也退出与主机之间的通信;
主机接收数据流程:
1、主机发送启动信号后,接着发送地址字节(其中R/W=1) :
2、对应的从机收到地址字节后,返回一个应答信号并向主机发送数据;
3、主机收到数据后向从机反馈一个应答信号ACK:
4、从机收到应答信号后再向主机发送下一个数据:
5、当主机完成接收数据后,向从机发送一个NAK,从机收到非应答信号后便停止发送;
6、主机发送非应答信号后,再发送一个停止信号,释放总线结束通信
stm32l431rct6的i2c引脚分配(本例我们使用引脚PB6和PB7为例)
二、了解sht20 stm32l431rct6的温湿度传感器引脚分配
三、开整 记得把串口使能了(这里我使用的是串口1),如下,其他的我相信你们都配好了(ctr+s就可以直接生成代码哦)
1、在 Core/Src 下创建并编写 SHT20 温湿度传感器的驱动源文件 sht20.c sht20.c代码如下 #include<stdio.h> #include "stm32l4xx_hal.h" #include "sht20.h" #include "tim.h" /* 通过该宏控制是使用 HAL 库里的 I2C 接口还是使用 GPIO 模拟串口的接口*/ #define CONFIG_GPIO_I2C #ifdef CONFIG_GPIO_I2C #include "gpioi2c.h" #else #include "i2c.h" #endif /*采样*/ int SHT20_Sample_data(uint8_t cmd, float *data) { uint8_t buff[2]; float sht20_data=0.
JS如何获取最近一个月或指定天数的日期,并以数组的形式存储 代码
num为传递的天数 (传递30查最近一个月) get_date(num) { let dateArray = [] //获取今天日期 let myDate = new Date() let today = myDate.getFullYear() + '-' + (myDate.getMonth() + 1) + "-" + myDate.getDate(); myDate.setDate(myDate.getDate() - num) let dateTemp; // 临时日期数据 let flag = 1; for (let i = 0; i < num; i++) { dateTemp = myDate.getFullYear() + '-' + (myDate.getMonth() + 1) + "-" + myDate.getDate() dateArray.push({ date: dateTemp }) myDate.setDate(myDate.getDate() + flag); } dateArray.
1、如何将类交给mmrotate框架容器管理 容器:框架中现有基本容器包括DATASETS, BACKBONES, LOSSES, DETECTORS。初始化容器:Registry(‘backbone’)中’backbone’为容器初始化配置文件。#/mmdet/models/builder.py 部分代码 from mmcv.utils import Registry,build_from_cfg BACKBONES = Registry('backbone') NECKS = Registry('neck') ROI_EXTRACTORS = Registry('roi_extractor') SHARED_HEADS = Registry('shared_head') HEADS = Registry('head') LOSSES = Registry('loss') DETECTORS = Registry('detector') 容器管理类的形式:#DATASETS容器 Registry(name=dataset, items={ 'CustomDataset': <class'mmdet.datasets.custom.CustomDataset'>, 'CocoDataset': <class'mmdet.datasets.coco.CocoDataset'>, 'CityscapesDataset': <class'mmdet.datasets.cityscapes.CityscapesDataset'>, 'ConcatDataset': <class'mmdet.datasets.dataset_wrappers.ConcatDataset'>, 'RepeatDataset': <class'mmdet.datasets.dataset_wrappers.RepeatDataset'>, 'XMLDataset': <class'mmdet.datasets.xml_style.XMLDataset'>, 'VOCDataset': <class'mmdet.datasets.voc.VOCDataset'>, 'WIDERFaceDataset': <class'mmdet.datasets.wider_face.WIDERFaceDataset'>}) 通过注解@ROTATED_DATASETS.register_module()可将数据集类注册到ROTATED_DATASETS容器。同理@ROTATED_BACKBONES.register_module()可将主干网类注册到ROTATED_BACKBONES容器。 2、如何实例化mmrotate框架容器管理的类 通过build_dataset(cfg),build_backbone(cfg),build_neck(cfg),build_loss(cfg)实例化相应容器中的类对象。#L1LossConfig loss = dict('type': 'L1Loss', 'loss_weight': 1.0) import mmdet.models.builder.build_loss import L1LossConfig l1Loss = build_loss(L1LossConfig.loss) 以上几个build_xxx(cfg)仅仅只是构建一个模型中的组件。 3、如何组装实例化mmrotate类对象(组件) 通过build_detectors(cfg)就可以将各个组件组装起来。cfg如下:# model settings model = dict( type='MaskRCNN', backbone=dict( type='ResNet', xxx ), neck=dict( type='FPN', xxx ), rpn_head=dict( type='RPNHead', xxx loss_cls=dict( type='CrossEntropyLoss', xxx), loss_bbox=dict(type='L1Loss', xxx), roi_head=dict( xxx mask_head=dict( type='FCNMaskHead', xxx loss_mask=dict( type='CrossEntropyLoss', xxx)))) 4、各个组件之间是怎么进行耦合的。 5、怎么知道单个组件需要传入哪些参数,才能自适应构建我们想要的组件。 6、mmrotate组织结构/功能。 通过 LOSSES = Registry(‘loss’)注册管理loss注册表中的所有loss,并通过build_loss(cfg)定制化生成我们所需的对象。这和Spring是一致的,通过ApplicationContext(application.
事件背景 框架漏洞收集
CVE-2018-7600有两个POC分别是7和8的,本文仅研究8版本的POC,与其它的文章不同的事,本文我将数据流向调试并记录下来了
漏洞说明 1. 漏洞原理:Drupal对表单请求内容未做严格过滤,因此,这使得攻击者可能将恶意注入表单内容,此漏洞允许未经身份验证的攻击者在默认或常见的Drupal安装上执行远程代码执行。
2. 组件描述:Drupal是使用PHP语言编写的开源内容管理框架(CMF),它由由内容管理系统和PHP开发框架共同构成,在GPL2.0及更新协议下发布。连续多年荣获全球最佳CMS大奖,是基于PHP语言最著名的WEB应用程序。
3. 影响版本: 7.x-8.x,本篇分析漏洞仅对版本8有效,版本7的是另外的利用点,但是CVE编号相同
漏洞复现 环境搭建:GitHub - drupal/drupal at 8.3.3
这里可能需要利用docker环境的命令配置一下,我自己的环境为:windows10、PHP7.1、电脑带有docker可使用composer命令生成vendor目录、需要提供yaml环境(https://www.cnblogs.com/yycode/p/16039854.html)、在php.ini文件中添加”yaml.decode_php=On“
然后访问/core/install.php进入安装界面,简单填数据库的信息安装即可
直接用payload
url : ?element_parents=account/mail/%23value&ajax_form=1
POST : form_id=user_register_form&mail[0][#lazy_builder][0]=passthru&mail[0][#lazy_builder][1][0]=whoami
命令执行成功
漏洞分析 漏洞的原因来源于框架的一个特点,即drupal采用引擎对数组渲染生成HTML表达
这里出现了两个问题,而这两个问题则就造成了漏洞的利用,一个是框架对数组数据的传入没有任何过滤,二是生成的表单最后会传入到drupal\core\modules\file\src\Element\ManagedFile.php的uploadAjaxCallback方法中解析,而在解析的过程中有几个框架自带的属性可以造成漏洞的利用
#access_callback
由Drupal使用来确定当前用户是否有权访问元素。#pre_render
在渲染之前操作渲染数组。#post_render
接收渲染过程的结果并在其周围添加包装。#lazy_builder
用于在渲染过程的最后添加元素。 #access_callback 标签虽然callback回调函数可控,但需要回调处理的字符串不可控,导致无法利用
由于对数组无任何过滤输入,即可传入这些自带的属性,造成回调函数的利用,不过有个问题就是数据怎么传入,如何触发漏洞,从头开始分析,构造的HTML表单的key值一般都是前期写死的,而我们经过分析必须得向表单传入可控键才能触发漏洞,这个问题的解决方法就是一个很正常的功能造成的
打个断点监听一下,运行以后如下
说明在buildform打的断点没有停下来,不过如果再以上述步骤一模一样操作一遍会发现
可以看到在断点处停下来了,第二次请求就停下来了,说明用户存在的话断点会走到最后,将表单返回
这就是一个一般网站常用的便捷功能,当注册的用户或邮箱存在时会保留上次输入的信息,而保留的这部分数据可以导致了数据的输入,这些数据最后会流入到drupal\core\modules\file\src\Element\ManagedFile.php::uploadAjaxCallback中解析,而现在还是没有解决,如何才能修改表单的键,根据其它师傅的分析才明白可以利用注册中图片的一个传输获得payload的大概身影,尝试抓取直接上传图片的请求,可以得到如下
由于格式是multipart/form-data,不太方便,再查看缓存的POST
利用burp抓到的url以及缓存的POST,提取几个关键的参数伪造为application/x-www-form-urlencoded类型的请求即可,经过分析大概提取了如下几个关键参数
url中element_parents参数的内容是定位到表单的一个位置最后提取其中的数据,比如上传图片时为user_picture/widget/0,则会将$form表单下的user_picture下的widget下的0提取出来无论为数组还是元素,代码实现如下
经过测试GET参数还有ajax_form为必须,不是很清楚具体作用,根据参数名和回显数据猜测应该是保存的表单
POST提取出了三处,分别为form_id、mail、name,其中form_id是必须定位到注册接口的,mail和name都可以传入数据,但是经过测试发现name有过滤,不接受数组的传输,而mail无任何过滤,因此采用mail传值
接下来从drupal\core\modules\file\src\Element\ManagedFile.php::uploadAjaxCallback开始审计
explode()函数会把element_parents内容以斜杆划分为几个值的数组,接下来步入getValue
大概作用为递归查询$form中是否有$form_parents,有的话最后把值返回,没有则返回空,因此最后$form为我们构造恶意的键对应的值,往下继续看
根据上述可以大概了解$form现在有三个键,一个是我们传入的,一个是#suffix,一个是#prefix,最后$form被传入$renderer->renderRoot(),跟进查看
继续跟进render()查看
就和套娃一样,继续跟进doRender()
由于没有#access和#access_callback因此如上条件判断皆可跳过,往下走
这里又添加了一个键值,下面的条件判断依旧可以跳过
这里即是最开始说的几个框架自带属性功能#lazy_builder,这也是我构造payload一个方法,因此如果利用的是#lazy_builder攻击,则进入条件判断查看,根据如上大概需要构造的payload有如下几个要求
#lazy_builder对应的值为数组
#lazy_builder对应的数组有且仅仅包含两个键
#lazy_builder下键为1对应的值为数组,测试如下
继续看下面
array_diff()函数用于比较两个(或更多个)数组的值,并返回差集,差集仅仅限于前减后
根据上例,我们必须保证$elements的键值小于等于$supported_keys且不能比在里面的数据多些什么,但是根据前面的数据我们很显然无法达到要求,其中#suffix、#prefix、还有后来添加的#cache,因此此处无法绕过,会导致报错,那么真的就没有办法了吗?确实,在这一层没有办法了,那我们就不能进入#lazy_builder这层条件了,这说明了#lazy_builder不可用吗?其实并不是,跳过这个条件继续看下去
其中经过数据处理$children为一个0数组 $elements['#children']为空$theme_is_implemented为false
已知$children为0数组,则提出来的值为0,因此就相当于将$elements中0键对应的值重新循环了一遍,而这次循环不再带有#suffix、#prefix等其它的键,那我们是不是可以将原本恶意的数据封装在0数组里,然后就可以绕过之前#lazy_builder条件里的一个判断了,那么解决了之前的那个困惑,后面直接看到关键条件
根据分析两个参数都可控的条件下利用回调函数call_user_func_array()最后实现命令注入,payload的构造为
URL : ?element_parents=account/mail/%23value&ajax_form=1
事件背景 框架漏洞收集
老外的CMS框架,比较复杂,数据流向太长,调试需要消耗较多的时间。
漏洞说明 1. 漏洞原理:2017年6月21日,Drupal官方发布了一个编号为CVE-2017- 6920 的漏洞,影响为Critical。这是Drupal Core的YAML解析器处理不当所导致的一个远程代码执行漏洞,影响8.x的Drupal Core。
2. 组件描述:Drupal是使用PHP语言编写的开源内容管理框架(CMF),它由由内容管理系统和PHP开发框架共同构成,在GPL2.0及更新协议下发布。连续多年荣获全球最佳CMS大奖,是基于PHP语言最著名的WEB应用程序。
3. 影响版本: 8.0.0~8.3.3
漏洞复现 环境搭建:GitHub - drupal/drupal at 8.3.3
这里可能需要利用docker环境的命令配置一下,我自己的环境为:windows10、PHP7.1、电脑带有docker可使用composer命令生成vendor目录、需要提供yaml环境(https://www.cnblogs.com/yycode/p/16039854.html)、在php.ini文件中添加”yaml.decode_php=On“
然后访问/core/install.php进入安装界面,简单填数据库的信息安装即可
登录后访问路径/admin/config/development/configuration/single/import
向输入框输入POC
点击import,可以看到phpinfo界面,说明POC攻击成功
漏洞分析 drupal8.3.3为开源框架,可以直接审计代码进行调试,根据网上相关漏洞的信息,可以得知本漏洞是yaml_parse()触发的yaml php反序列化,于是先找到该函数的出现的点
有且仅有一个,因此可以断定就是这里,进入看看
这里可以在PHP手册看到该函数的作用
可以看到第一个参数为YAML格式字符串,而函数的作用为将全部或部分 YAML 文档流转换为 PHP 变量,还有一个注意事项
大概意思为:如果使用!php/object则会进行一次反序列化,这个开关由ini的yaml.decode_php控制,因此大概能知道这个函数如果在特定条件下会触发反序列化,而我们现在需要的是控制第一个参数,即$raw
步入Yaml.php::decode查看是否能实现与YamlPecl.php::decode进行链接,步入getSerializer查看一下
可以看到,只要存在yaml环境即可步入第一个条件判断,这也是为什么需要yaml环境了,再去看有没有可控参数,最后定位到ConfigSingleImportForm.php文件
可以看到Yaml::decode()中参数可控因此直接在这利用即可,不过还有一个问题就是利用哪个文件进行反序列化,这个需要查看多个php类文件,最后定位在
vendor\guzzlehttp\guzzle\src\Cookie\FileCookieJar.php
\vendor\guzzlehttp\psr7\src\FnStream.php
一个可以直接写webshell,另一个是可以执行无参函数
最后POC为:
<?php namespace GuzzleHttp\Psr7; class FnStream { public function __construct(array $methods){ $this->methods = $methods; // Create the functions on the class foreach ($methods as $name => $fn) { $this->{'_fn_' .
【摘要】在云原生技术发蓬勃发展的时代,底层承载应用的容器很重要,然而,单一容器隔离技术已经无法满足各种场景的要求,不同的场景都需要不同的容器形态来承载,从而产生了不同的沙箱技术。本文结合沙箱容器发展的历程,介绍华为云多沙箱容器运行时 Kuasar 项目的优势,并为开发者演示 Kuasar 的安装运行方式,开启多沙箱容器运行时的上手实践体验!
文章目录 前言沙箱容器的发展容器时代沙箱崛起 Kuasar 项目简介项目简介Kuasar定位MicroVM SandboxerApp Kernel SandboxerWasm SandboxerKuasar管理模型的变化性能表现启动时间测试内存消耗测试 Kuasar 安装部署预准备安装部署下载并源码编译配置 cotainerd 运行组件启动kuasar配置containerd环境变量 运行容器运行vmm沙箱运行quark沙箱运行wasm沙箱查看现有Pod和清空演示 总结Reference 前言 在一年一度的云原生开源领域顶级峰会KubeCon + CloudNativeCon Europe 2023上,由华为云、中国农业银行、openEuler 社区和 CNCF 项目 WasmEdge 等联合发起的云原生多沙箱容器运行时 Kuasar 正式宣布开源,受到云原生社区、Rust 社区和云厂商们的广泛关注和热烈讨论。
全新云原生开源项目Kuasar,其结合了华为云多年生产业务实践以及对沙箱技术发展的思考,基于业界新兴的沙箱接口实现。在保留传统容器运行时功能的基础上,Kuasar通过全面Rust化以及优化管理模型和框架等手段,进一步降低管理开销、简化调用链路,灵活扩展对业界主流沙箱技术的支持,实现云原生业务场景全覆盖。此外,通过支持多安全沙箱共节点部署,Kuasar可以充分利用节点资源、降本增效,为用户提供更安全高效的沙箱场景解决方案。
沙箱容器的发展 容器时代 早在 2013 年,docker 横空出世,标志着容器时代到来。最初的容器技术,其实就是利用 Linux 内核提供的命名空间 Namespace 和控制组 Cgroup 功能,实现容器进程之间的资源隔离和限制。在容器时代,容器就是 docker 里唯一的一等公民。
不久,2014年,容器编排领域诸侯争霸,随着 Kubernetes 最终成为主流的容器编排工具,Pod也成为容器编排领域的一等公民,为了兼容 Pod 这一概念,docker 引入了 pause 容器。
然而,pause 容器的引入常常让开发者感到困惑,因为 Pod 与 pause 容器之间存在着很多差异。在 kubernetes 中,Pod 是一组容器逻辑和物理资源的载体,而 pause 容器只是提供了容器间共享的 namespace 而已。此外,容器运行时里有很多冗余和复杂的判断逻辑用于区分 pause 容器和用户容器,使得代码阅读和开发变得困难。
1 Pillow简介 1.1 PIL和Pillow PIL( Python Imaging Library)是 Python 的第三方图像处理库,由于其功能丰富,API 简洁易用,因此深受好评。
自 2011 年以来,由于 PIL 库更新缓慢,目前仅支持 Python 2.7 版本,这明显无法满足 Python3 版本的使用需求。于是一群 Python 社区的志愿者(主要贡献者:Alex Clark 和 Contributors)在 PIL 库的基础上开发了一个支持 Python3 版本的图像处理库,它就是 Pillow。
Pillow 不仅是 PIL 库的“复制版”,而且它又在 PIL 库的基础上增加了许多新的特性。Pillow 发展至今,已经成为了比 PIL 更具活力的图像处理库。
Pillow 的初衷只是想作为 PIL 库的分支和补充,如今它已是“青出于蓝而胜于蓝”。
除了 PIL 和 Pillow 库之外,Python 还提供了一些其他图像处理库:
Scikit-image:一款基于 scipy 科学计算的图像处理软件包,以数组的形式对图像进行处理;OpenCV:其实是一个 C++ 图像处理库,不过它提供了 Python 语言的接口。 Pillow 是 Python 中较为基础的图像处理库,主要用于图像的基本处理,比如裁剪图像、调整图像大小和图像颜色处理等。与 Pillow 相比,OpenCV 和 Scikit-image 的功能更为丰富,所以使用起来也更为复杂,主要应用于机器视觉、图像分析等领域,比如众所周知的“人脸识别”应用。
Pillow 库(有时也称 PIL 库) 是 Python 图像处理的基础库,它是一个免费开源的第三方库,Pillow 提供了非常强大的图像处理功能,它能够很轻松地完成一些图像处理任务。与 Python 的其他图像处理库相比(OpenCV、Scikit-image 等),Pillow 库简单易用,非常适合初学者学习。
文章目录 什么是HTMLHTML规范标签的种类开闭合标签整合标签标签中的属性 我的第一个HTML 什么是HTML Hyper Text Markup Language 超文本标记语言
超文本:表示页面上的一切要素,正如Java中的万物皆对象一样,在网页中包含 普通的文本样式 结构 视频 音频等都可以称之为超文本。
标记:也称之为标签,英文为Tag,页面上的一切要素都是用标记来渲染,包括样式 结构视频 音频等一系列要素都有标签来进行渲染,比如我们需要进行一个换行操作,点击键盘上的回车键是无效的,必须使用标签进行换行。
HTML规范 1993年由W3C世界互联网组织发布了第一版的Html规范,此规范初步了规定了各种标签的使用方式,Html可以同时渲染页面的结构和样式,目前2020年使用的版本已经迭代到第五版也就是著名的html5,迄今为止依然存在部分的浏览器差异性。
html文件以.html 或者 .htm 结尾,必须以浏览器打开,目前世界上常见的浏览器主要有以下几种,也是w3c的主要成员 谷歌 火狐 opera safari和ie,这五种浏览器都是用了自己独特的内核。我国没有自己独立内核的浏览器。
标签的种类 开闭合标签 <tagName>需要被嵌套的内容</tagName> <!--例如--> <i>文本倾斜</i> <b>文本加粗</b> 整合标签 一般用来渲染特定的结构等
<tagName /> 或者 <tagName> 以上两种写法在Html5规范中都是正确的
标签中的属性 在标签中可以设置多个属性
<tagName 属性名1="属性值1" 属性名2="属性值2" /> 属性多用来补充标签的一些特性,例如宽高等辅助参数
我的第一个HTML html文件以.html和.htm为后缀,全文不区分大小写具有较高的容错性,浏览器具有一个标签解析器和脚本解析器,从上往下解析
用户书写的html页面,如果出现严重的错误,则无法显示相应的结构和样式在html页面上主要存在以下三种
结构(html) 页面上有什么 一个人身高 体型 素颜
样式(css html*)的这个东西是什么样子的打扮化妆以后的样子
动作(js) 页面上能够具有什么操作 这个人的谈吐举止
在1996年css出现之前html也能够渲染页面样式,之后样式被css取代
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>我的第一个html</title> </head> <body> <center> <div id="
windows/linux git安装 windows 下载linux 下载设置配置 windows 下载 不建议使用官网下载,非常慢
官网
建议使用镜像网站下载
国内镜像
linux 下载 建议使用命令行下载
sudo apt-get install git 设置 linux 使用命令行,windows在安装完git使用git bash运行下面命令配置邮箱和用户
git config --global user.email "***@***.com" //邮箱 git config --global user.name "***" 配置 linux 使用命令行,windows使用git bash运行下面命令生成ssh key
ssh-keygen -t rsa -C ***@***.com //邮箱 注意: windows需要查看config文件中是否有下面配置没有需要加上
$ cat ~/.ssh/config Host * HostKeyAlgorithms +ssh-rsa PubkeyAcceptedKeyTypes +ssh-rsa cat ~/.ssh/id_rsa.pub //查看ssh公钥 将公钥复制拷贝到gitlab或者github这种远程的git仓库添加ssh-key的位置即可
然后linux 使用命令行,windows使用git bash ,用git clone就可以下载远程仓库中的代码了
137.CODA: A Real-World Road Corner Case Dataset for Object Detection in Autonomous Driving 用于自动驾驶中物体检测的真实世界道路角落案例数据集
ECCV2022
文章结构:
摘要
1.引言
2.相关工作
3.CODA属性
4.CODA的构造
4.1概述 4.2识别潜在的角落案例 4.3进一步检查 5.实验
5.1实验细节 5.2结果 6.讨论
7.结论
附录
1.针对什么问题(摘要) 当代用于自动驾驶的深度学习物体检测方法通常假定普通交通参与者的类别是固定的,如行人和汽车。
大多数现有的检测器无法检测到不常见的物体和角落的情况(例如,一只狗穿过街道),这在某些情况下可能会导致严重的事故,使得可靠的自动驾驶在现实世界的应用时间线不确定。
阻碍真正可靠的自动驾驶系统发展的一个主要原因是缺乏公共数据集来评估角落案例中物体检测器的性能。
个人理解:
问题:用于自动驾驶的现存检测方法通常假定交通参与者的类别是固定的,如行人和汽车。
不能识别不常见的物体和角落(如一只狗穿过街道、失控的轮胎、翻转的卡车),可能会导致交通事故。
原因:没有一个这样的数据集来评估角落案例中物体检测器的性能。
2.解决办法(摘要) 引入了一个名为CODA的数据集。
该数据集由1500个真实世界驾驶场景组成,每个场景平均包含四个物体级别的角落案例,横跨30多个物体类别。
2.1 引入CODA数据集的必要性(摘要、相关工作) (相关工作):
以前的检测器大多是在封闭世界环境中训练的,它只能检测属于预先定义的语义类别集的物体。
为了建立一个真实世界的感知系统,开放世界检测引起了更多关注,它可以明确地检测出未见过类别的物体是未知的。
(摘要):
在CODA上,在大规模自动驾驶数据集上训练的标准物体检测器的性能在mAR上显著下降到不超过12.8%。
用最先进的物体检测器也不能可靠地识别CODA中的物体。
希望CODA数据集能够促进对现实世界自动驾驶的可靠检测的进一步研究。
mAR:
在深度学习中,mAR通常指的是“移动平均准确率”(moving average accuracy)。这是一种评估模型性能的指标,在训练过程中使用。它是通过计算模型在一段时间内预测正确的样本数量的移动平均值来衡量模型的准确率。
移动平均准确率可以帮助我们观察模型在训练过程中的稳定性和趋势。通过跟踪模型的移动平均准确率,我们可以了解模型是否在逐渐改进,或者是否出现了过拟合或欠拟合的情况。
为了计算移动平均准确率,我们首先定义一个窗口大小(例如,最近100个批次)。然后,每当经过一个新的批次时,我们计算该批次的准确率,并将其添加到移动平均值中。随着新的批次不断到来,旧的批次会从移动平均中剔除,以保持固定大小的窗口。
通过观察移动平均准确率,我们可以更好地理解模型的整体表现,并对其进行调整和优化。
必要性个人理解:并且在CODA上训练的物体检测器性能显著下降;用最先进的物体检测器也不能可靠地识别CODA中的物体。
3.创新点/贡献点(引言) 提出了CODA,第一个真实世界的道路角落案例数据集,作为开发完全可靠的自动驾驶车辆的基准。
评估了各种最先进的物体检测器(Cascade R-CNN [5], Deformable DETR [49], and Sparse R-CNN [39]),表明真正可靠的自动驾驶系统可能还远远没有达到。