main
forget_the_bright 1 year ago
parent cdef53f505
commit f27ac51a79

@ -24,5 +24,15 @@ namespace DIWebApi.Controllers
{
return calculate.Count;
}
/// <summary>
/// 写入文件
/// </summary>
/// <param name="Path">文件路径</param>
/// <param name="content">文件内容</param>
[HttpGet("build")]
public void buildCount()
{
System.IO.File.WriteAllText("", "");
}
}
}

@ -0,0 +1,82 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using WebMVCApi.config;
namespace WebMVCApi.Controllers
{
[Route("halo/")]
[ApiController]
public class DBController : ControllerBase
{
[HttpGet("GetHaloContent")]
public IActionResult GetHaloContent()
{
var list = new ArrayList();
var dbx = new HaloDbContext();
var conn = dbx.Database.GetDbConnection();
if(conn.State != System.Data.ConnectionState.Open)
{
conn.Open();
}
using (var cmd = conn.CreateCommand())
{
// cmd.CommandText = "SELECT\r\n\tt1.id,\r\n\tIFNULL(GROUP_CONCAT( t5.NAME ) , '')AS cates ,\r\n\tIFNULL(GROUP_CONCAT( t6.NAME ) , '')AS tags ,\r\n\tt2.original_content,\r\n\tt1.title\r\nFROM\r\n contents t2 \r\n\tLEFT JOIN posts t1\r\n\tON t1.id = t2.post_id\r\n\t\r\n LEFT JOIN post_categories t3 \r\n\tON t1.id = t3.post_id\r\n\t\r\n\tLEFT JOIN post_tags t4 \r\n\tON t1.id = t4.post_id\r\n\t\r\n\tLEFT JOIN categories t5\r\n\tON t3.category_id = t5.id\r\n\t\r\n\tLEFT JOIN tags t6\r\n\tON t4.tag_id = t6.id\r\nGROUP BY\r\n\tt2.post_id";
cmd.CommandText = "SELECT\r\n\tt1.id,\r\n\tIFNULL(GROUP_CONCAT( t5.NAME ) , '')AS cates ,\r\n\tIFNULL(GROUP_CONCAT( t6.NAME ) , '')AS tags ,\r\n\tt2.original_content,\r\n\tt1.title,\r\n\tt1.create_time\r\nFROM\r\n contents t2 \r\n\tLEFT JOIN posts t1\r\n\tON t1.id = t2.post_id\r\n\t\r\n LEFT JOIN post_categories t3 \r\n\tON t1.id = t3.post_id\r\n\t\r\n\tLEFT JOIN post_tags t4 \r\n\tON t1.id = t4.post_id\r\n\t\r\n\tLEFT JOIN categories t5\r\n\tON t3.category_id = t5.id\r\n\t\r\n\tLEFT JOIN tags t6\r\n\tON t4.tag_id = t6.id\r\nGROUP BY\r\n\tt2.post_id";
var read = cmd.ExecuteReader();
while (read.Read()) {
var id = read.GetInt32(0);
var cates = read.GetString(1);
var tags = read.GetString(2);
var content = read.GetString(3);
var title = read.GetString(4);
var createTime = read.GetDateTime(5);
var setCates = cates.Split(',').ToHashSet();
var setTags = tags.Split(',').ToHashSet();
string head =
$"---\r\n" +
$"icon: edit\r\n" +
$"date: {createTime.ToString("yyyy-MM-dd")}\r\n";
if (setCates.First()!="")
{
head += $"category:\r\n";
}
foreach (var cate in setCates)
{
if (!cate.Equals("")) {
head += $" - {cate}\r\n";
}
}
if (setTags.First() != "")
{
head += $"tag:\r\n";
}
foreach (var tag in setTags)
{
if (!tag.Equals("")) {
head += $" - {tag}\r\n";
}
}
head +=
"headerDepth: 5\r\n" +
"---\r\n\n\n" +
$"# {title}\r\n";
title = title.Replace("/", "");
System.IO.File.WriteAllText($"./md/{title}.md", head+ content);
Console.WriteLine(id);
list.Add(content);
}
}
return Ok(list);
}
}
}

@ -19,7 +19,7 @@ if (app.Environment.IsDevelopment())
app.UseHttpsRedirection();
app.UseAuthorization();
app.UseResponseCaching();
app.MapControllers();
app.Run();

@ -7,6 +7,14 @@
</PropertyGroup>
<ItemGroup>
<Compile Remove="Services\**" />
<Content Remove="Services\**" />
<EmbeddedResource Remove="Services\**" />
<None Remove="Services\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>

@ -0,0 +1,19 @@
using Microsoft.EntityFrameworkCore;
namespace WebMVCApi.config
{
public class HaloDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
optionsBuilder.UseMySql("server=local.wuanwanghao.top;port=3307;user=root;password=ks125930.;database=blog-db",
new MySqlServerVersion(new Version(5, 7, 35)));
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
}
}
}

@ -0,0 +1,42 @@
---
icon: edit
date: 2023-04-13
category:
- Linux
tag:
- pacman
- Arch
- ArchLinux
headerDepth: 5
---
# Arch 关于pacman的常用指令
## 关于pacman的常用指令:
### 5.1 pacman -S 指令:安装
```bash
sudo pacman -S #安装软件
sudo pacman -Sy #获取最新打软件情况,如果已经是最新了,直接会提示已经更新到最新了。
sudo pacman -Syy #强行更新你的应用的软件库(源)
sudo pacman -Su #更新所有软件
sudo pacman -Syu #更新软件源并更新你的软件
sudo pacman -Syyu #强行更新一遍,再更新软件
sudo pacman -Ss <pkg_name> #查询所有软件名里面带有<pkg_name>相关的软件。
sudo pacman -Sc #删除软件/var目录下的缓存
```
### 5.2 pacman -R 指令:删除
```bash
sudo pacman -R <pkg_name> #删除软件
sudo pacman -Rs <pkg_name> #删除软件,并删除<pkg>所有的依赖包
sudo pacman -Rns <pkg_name> #删除软件,并删除<pkg>所有的依赖,并删掉<pkg>的全局配置文件。 推荐!!
```
### 5.3 pacman -Q 指令:查询
```bash
sudo pacman -Q #显示出所有软件 sudo pacman -Q | wc -l 查询数量
sudo pacman -Qe #查询所有自己安装的软件
sudo pacman -Qeq #查询所有自己安装的软件,只显示包名,不显示版本号等
sudo pacman -Qs <pkg_name> #查询本地安装的所有带<pkg_name>的软件
sudo pacman -Qdt #查询所有孤儿软件,不再被需要的。
sudo pacman -Qdtq #查询所有不再被依赖的包名
```

@ -0,0 +1,161 @@
---
icon: edit
date: 2022-11-12
category:
- 系统配置
- Linux
- nodejs
tag:
- Arch
- ArchLinux
- nodejs
- nvm
- pm2
- pm2-logrotate
headerDepth: 5
---
# ArchLinux 安装nvm nodejs并配置安装pm2 pm2-logrotate
### 安装nvm
#### 下载安装脚本
nvm 官网地址 [https://github.com/nvm-sh/nvm](https://github.com/nvm-sh/nvm)
安装前提服务器配置好```git``` ```curl``` 或者 ```wget```
网络好的同学可以使用官网的例子
```
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash
```
```
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash
```
网络不好的同学可以使用我配置好的脚本
```
curl -o- https://local.wuanwanghao.top:9000/test/nvm_install.sh | bash
```
```
wget -qO- https://local.wuanwanghao.top:9000/test/nvm_install.sh | bash
```
#### 配置环境变量
一般centos 和 ubuntu 环境安装的同学就已经可以使用 nvm 了 但是Arch linux 同学还不能使用,我们要配置下环境变量
```
vim ~/.profile
```
##### 写入配置
```
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
export NVM_NODEJS_ORG_MIRROR=https://npm.taobao.org/mirrors/node/
export NVM_IOJS_ORG_MIRROR=http://npm.taobao.org/mirrors/iojs
```
##### 应用配置
```
source ~/.profile
```
#### nvm 常用命令
```shell
nvm install stable ## 安装最新稳定版 node
nvm install <version> ## 安装指定版本
nvm uninstall <version> ## 删除已安装的指定版本
nvm use <version> ## 切换使用指定的版本node
nvm ls ## 列出所有安装的版本
nvm ls-remote ## 列出所有远程服务器的版本
nvm current ## 显示当前的版本
nvm alias <name> <version> ## 给不同的版本号添加别名
nvm unalias <name> ## 删除已定义的别名
nvm reinstall-packages <version> ## 在当前版本 node 环境下,重新全局安装指定版本号的 npm 包
nvm alias default [node版本号] ##设置默认版本
```
### 安装nodejs
nvm 安装 最新发行版
```shell
nvm install stable
```
#### 配置npm 源
```shell
npm config set registry https://registry.npmjs.org
```
#### 安装yarn
```shell
npm install -g yarn
```
#### 配置yarn源
```shell
yarn config set registry https://registry.npm.taobao.org
```
### 安装pm2 进程管理工具
```
npm install -g pm2
```
#### pm2 常用命令
```txt
pm2 start app.js --name="fx67ll" 启动并命名为fx67ll没有命名的话后续可以用id替代name
pm2 start app.js --watch 当文件变化时自动重启应用
pm2 start script.sh 启动bash脚本
pm2 list 查看所有启动的应用列表
pm2 monit 显示每个应用程序的CPU和内存占用情况
pm2 show [app-id/app-name] 显示指定应用程序的所有信息
pm2 log 显示应用程序的日志信息
pm2 log [app-id/app-name] 显示指定应用程序的日志信息
pm2 flush 清空所有日志文件
pm2 stop all 停止所有应用程序
pm2 stop [app-id/app-name] 停止指定应用程序
pm2 restart all 重启所有应用程序
pm2 restart [app-id/app-name] 重启指定应用程序
pm2 delete all 关闭并删除所有应用程序
pm2 delete [app-id/app-name] 删除指定的应用程序
pm2 reset [app-id/app-name] 重置重启数量
pm2 startup 创建开机自启动命令
pm2 save 保存当前应用列表
pm2 resurrect 重新加载保存的应用列表
pm2 update 保存进程杀死并重启进程一般用于更新pm2版本
pm2 ecosystem 生成一个示例json配置文件
```
#### 启动应用
```
pm2 start mayfly
```
#### 查看应用
```
pm2 list
```
![image-1668258326917](https://local.wuanwanghao.top:9000/test/test/image-1668258326917.png)
#### 设置开机启动
```
pm2 startup
pm2 save
```
```运行pm2 startup 在/etc/init.d/目录下生成pm2-root的启动脚本且自动将pm2-root设为服务。```
#### pm2 查看日志
```
pm2 logs mayfly
```
![image-1668258487288](https://local.wuanwanghao.top:9000/test/test/image-1668258487288.png)
**同时我们也可以使用 tail -f 查看指定的文件的日志**
```
tail -200f /root/.pm2/logs/main.out.log
```
```但是pm2自带的日志功能是不支持自动分割的这就会导致随之时间的推移我们的日志文件会越来越大不但会影响性能在后期排查问题的时候也会很麻烦这时我们就可以使用pm2-logrotate插件来解决上面的问题。安装也是非常简单```
#### 安装pm2-logrotate
```
pm2 install pm2-logrotate
```
通过 pm2 conf pm2-logratate 可以查看详细的配置
![image-1668258663216](https://local.wuanwanghao.top:9000/test/test/image-1668258663216.png)
![image-1668258687030](https://local.wuanwanghao.top:9000/test/test/image-1668258687030.png)
比如我们可以设置日志文件大小为1KB
```
pm2 set pm2-logrotate:max_size 1k
```
修改完不要忘记重启服务
```
pm2 restart all
```
当大小达到1KB就会自动分割格式如main-out__2022-07-29_11-00-32.log 的文件。
pm2日志文件储存在 /root/.pm2/logs 文件夹下。
![image-1668258827133](https://local.wuanwanghao.top:9000/test/test/image-1668258827133.png)

@ -0,0 +1,182 @@
---
icon: edit
date: 2022-11-12
category:
- 系统配置
- Linux
tag:
- linux
- Arch
- ArchLinux
headerDepth: 5
---
# ArchLinux 安装指南
### 准备工作
在开始安装 Arch Linux 之前,需要先下载安装映像文件并创建好虚拟机环境。
#### 下载安装镜像
下面是 Arch Linux 官方的安装文件下载地址:
[Arch Linux - Downloads](https://archlinux.org/download/) Arch Linux 安装映像下载地址。
点击并打开这个页面后,可以看到目前 Arch Linux 最新的版本和下载包的文件信息。往下翻页,在页面下方有各个国家可用的下载加速镜像。
选择距离自己所在位置最近的加速镜像可以有效提升安装包的下载速度,我们找到 "China",然后选择其中一个任意可用的加速镜像地址,比如 163.com。
![image-1668233139961](https://local.wuanwanghao.top:9000/test/test/image-1668233139961.png)
点击镜像链接后,就会打开一个类似文件列表的页面,我们选择 iso 后缀的那个文件,直接点击文件名称进行下载操作。
![image-1668233216068](https://local.wuanwanghao.top:9000/test/test/image-1668233216068.png)
创建虚拟机
VMWARE是一个开源免费的虚拟机软件。下载后安装创建一个新的虚拟机并把上面下载的 ISO 文件加载到启动光盘。
### 安装 Arch Linux
启动虚拟机,一切操作正常的话,开机后会看到如下画面
![image-1668233316725](https://local.wuanwanghao.top:9000/test/test/image-1668233316725.png)
通过上下方向键可以自由选择相关的菜单。选择第一项“Arch Linux Install medium (x86_64, BIOS)“,按回车键确认,进入 Arch Linux 的安装环境。
![image-1668233418977](https://local.wuanwanghao.top:9000/test/test/image-1668233418977.png)
#### 磁盘分区
开始正式安装系统前,需要先对硬盘做分区操作。这需要指定可操作的硬盘,可以通过以下命令来确定当前系统有哪些可用的硬盘设备:
```shell
fdisk -l
```
命令会返回类似如下的输出结果:
![image-1668233499398](https://local.wuanwanghao.top:9000/test/test/image-1668233499398.png)
其中 /dev/sda 就是一个可用的硬盘设备。记下这个名称,等下分区时会用的上。在正式开始分区前,需要先确定好分区规划。
对于正式使用的场景,我会建议你多参考一些 Linux 分区方案,可以使日后在磁盘的利用方面更加妥当。不过对于本文仅做体验的场景,我自己的方案如下:
1. 一个交换分区,大小为 1 GiB。
2. 最后所有的空间都留给根分区。
有了分区方案,输入以下命令开始分区操作:
```shell
fdisk /dev/sda
```
命令执行后,会进入如下界面:
![image-1668233910191](https://local.wuanwanghao.top:9000/test/test/image-1668233910191.png)
这就是 fdisk 提供的分区操作界面了,通过如下操作来创建一个 1 GiB 的交换分区:
1. 输入 n 新建分区。
2. 输入 p 新建主分区。
3. 分区编号输入 1。
4. 开始扇区不用输入,直接回车键进入下一项。
5. 结束扇区输入 +1G。
然后用同样的流程完成主分区的创建。这一步的分区号为 2后面的扇区输入都保持空然后直接回车键就可以了程序会自动分配剩余的所有空间。
以上操作完成后,输入 w 写入分区信息。然后再次输入 fdisk -l 命令,会发现输出信息中多了如下内容:
![image-1668233994293](https://local.wuanwanghao.top:9000/test/test/image-1668233994293.png)
这说明分区操作成功了。
#### 格式化分区
硬盘分区后还需要做格式化操作。Linux 针对不同的分区类型,提供了有不同的格式化命令。首先来格式化交换分区:
```shell
mkswap /dev/sda1
```
主分区使用 ext4 格式的分区:
```shell
mkfs.ext4 /dev/sda2
```
#### 挂载分区
完成分区格式化后,接下来需要挂载分区。首先挂载根分区:
```shell
mount /dev/sda2 /mnt
```
然后启用交换分区:
```shell
swapon /dev/sda1
```
#### 安装系统
完成了以上磁盘操作步骤,就可以正式开始安装 Arch Linux 系统了。不过开始之前,为了提升安装包的下载速度,可以通过以下命令自动更新并保存 5 个速度最快的软件包镜像加速地址:
```shell
reflector \
--save /etc/pacman.d/mirrorlist \
--country China \
--protocol https \
--latest 5
```
然后安装基础软件包Linux 内核,常见硬件的固件和常用软件工具:
```shell
pacstrap /mnt base linux linux-firmware dhcpcd openssh xfsprogs man net-tools vim sudo networkmanager
```
等待安装完成。
结束后,生成新的自动挂载文件,并写入到新安装的系统:
``` shell
genfstab -U /mnt >> /mnt/etc/fstab
```
然后进入到新安装的系统:
```shell
arch-chroot /mnt
```
接下来,将开始对新系统做配置操作。
### 配置 Arch Linux
#### 配置网络
启用相关服务:
```shell
systemctl enable dhcpcd
systemctl enable NetworkManager
```
#### 配置时区
Arch Linux 默认为 UTC 时区,调整为国内时区使用下面的命令:
```shell
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
```
配置本地字符编码
- 编辑 /etc/locale.gen 文件,取消 en_US.UTF-8 UTF-8 这一行前的注释信息。
- 执行 locale-gen 命令生成本地字符集信息。
- 创建 /etc/locale.conf 文件内容为LANG=en_US.UTF-8。
```使用 en_US.UTF-8 而不使用中文字符编码的原因是为了避免系统输出无法显示的中文信息,以方便排查问题。```
#### 配置用户
设置 root 账号密码:
```shell
passwd
```
添加新的普通用户,并加入到 wheel 用户组,以方便使用 sudo 命令来执行一些需要超级用户权限的操作:
```shell
useradd -m -G wheel -s /bin/bash zzxworld
```
```最后面的 zzxworld 是新用户名称,需要自己定义。```
#### 配置系统引导程序
安装 GRUB 启动加载器:
```shell
pacman -S grub
```
安装 GRUB 引导信息至指定的硬盘:
```shell
grub-install --recheck /dev/sda
```
生成并写入 GRUB 配置信息:
```shell
grub-mkconfig -o /boot/grub/grub.cfg
```
#### 登录新系统
完成以上步骤后Arch Linux 的基础安装工作就完成了,可以尝试退出安装环境并进入新系统。
首先输入以下命令退出 chroot 环境:
```shell
exit
```
然后卸载之前挂载的分区:
```shell
umount -R /mnt
```
重新启动系统。
```shell
reboot
```
正常的话,应该会看到新的启动选项选择界面:
![image-1668234594711](https://local.wuanwanghao.top:9000/test/test/image-1668234594711.png)
直接按回车键,就可以进入新安装的 Arch Linux 系统了。

@ -0,0 +1,19 @@
---
icon: edit
date: 2023-02-09
category:
- .Net
headerDepth: 5
---
# C# .Net Standard 类库版本 对应。.NetCore 和 .Net Framework 支持
![image-1675923628386](https://local.wuanwanghao.top:9000/test/test/image-1675923628386.png)
.Net Standard 是一种规范
.Net Core 的出现是微软为了在 .Net 复杂概念中一种解决方法。并且实现了跨平台的功能 .Net Core 可以看做是一种新类型的规范 ,当然也有相应的实现。
当然 .Net Core 也支持 .Net Standard 规范。
![image-1675924247126](https://local.wuanwanghao.top:9000/test/test/image-1675924247126.png)

@ -0,0 +1,25 @@
---
icon: edit
date: 2023-02-09
category:
- .Net
headerDepth: 5
---
# C# 修改NuGet 包的安装路径
NuGet 是 .NET 平台下的一个免费、开源的包管理开发工具。
修改全局包管理目录
通过 NuGet 安装包时NuGet 先将包下载至一个统一的目录默认路径是C:\Users\用户名\.nuget\packages
下载的包多了以后,会导致 C 盘空间被大量占用。我们可以通过修改配置将其指定到自定义的目录下。
搜索 NuGet.Config 文件默认位置是C:\Users\用户名\AppData\Roaming\NuGet在根节点下添加如下配置
``` xml
<config>
<add key="globalPackagesFolder" value="D:\env\nuget\packages" />
</config>
```
其中添加 value 修改为要保存的位置 如果不生效可以修改下在电脑的 C:\Program Files (x86)\NuGet\Config 下有一个 ```Microsoft.VisualStudio.Offline.config``` 文件 添加同样的配置

@ -0,0 +1,23 @@
---
icon: edit
date: 2023-03-02
category:
- .Net
headerDepth: 5
---
# C# 链接 docker 中 sqlserver 的一下问题解决
System.ComponentModel.Win32Exception (0x80090325): 证书链是由不受信任的颁发机构颁发的 这是远程链接的数据库中有不信任的证书。
windows 下出行此问题 在链接字符串中添加
```
Encrypt=True;TrustServerCertificate=True;
```
The login is from an untrusted domain and cannot be used with Int
egrated authentication.
出现此问题就是 使用的windows 身份认证登录和 sqlserver 认证登录同时使用了确定一个把windows 身份认证登录 删掉
```
Trusted_Connection=True;
```

@ -0,0 +1,44 @@
---
icon: edit
date: 2023-01-31
category:
- cpp
headerDepth: 5
---
# C++ 字符串比较的一下方法
字符串比较是否包含
```
bool canConstruct(std::string ransomNote, std::string magazine)
{ //字符串等长情况
int magazineLength =magazine.length();
int ransomNoteLength =ransomNote.length();
if(magazineLength == ransomNoteLength){
for (size_t i = 0; i < ransomNoteLength; i++)
{
if(magazine[i]!=ransomNote[i]){
return false;
}
}
return true;
}
if (magazineLength > ransomNoteLength)
{
int temp= 0;
for (size_t i = 0; i < magazineLength; i++)
{
if(magazine[i]==ransomNote[temp]){
temp++;
}else{
temp = 0;
}
if(temp==ransomNoteLength){
return true;
}
}
}
return false;
}
```

@ -0,0 +1,601 @@
---
icon: edit
date: 2022-10-14
category:
- cpp
headerDepth: 5
---
# C++实现AES加解密算法
# AES 头文件
## CAES.h
```Cpp
#pragma once
class CAES
{
public:
CAES(const char* key);
virtual ~CAES();
/**
* 加密
* @param in 输入加密数据
* @param inlen 输入加密数据长度
* @param outlen 输出加密后数据长度
* @param fill 如果不是16的整数倍是否用0值补全。 true:用0值补全, false:用xor加密多余的数据
* @return 返回加密后数据
*/
void* Encrypt(void* in, int inlen, int& outlen, bool fill = false);
/**
* 解密
* @param in 输入解密数据
* @param inlen 输入解密数据长度
* @param outlen 输出解密后数据长度
* @return 返回解密后数据
*/
void* Decrypt(void* in, int inlen, int& outlen);
private:
// S 盒变换
unsigned char Sbox[256];
// 逆 S 盒变换
unsigned char InvSbox[256];
// 密钥
unsigned char w[11][4][4];
private:
/**
* 密钥扩展函数 - 对128位密钥进行扩展得到 w[11][4][4]
* @param key 16位密钥
*/
void KeyExpansion(const char* key);
/**
* 异或加解密
* @param in 加解密输入数据
* @param len 加解密输入数据长度
*/
void Xor(unsigned char* in, int len);
/**
* 加密传入的数组大小必须是16字节
* @param data 加密数据
*/
void Encrypt(unsigned char* data);
/**
* 解密传入的数组也必须是16字节
* @param data 解密数据
*/
void Decrypt(unsigned char* data);
/**
* S 盒变换
* @param state 变换数据
*/
void SubBytes(unsigned char state[][4]);
/**
* 行变换
* @param state 变换数据
*/
void ShiftRows(unsigned char state[][4]);
/**
* 列变换
* @param state 变换数据
*/
void MixColumns(unsigned char state[][4]);
/**
* 与扩展密钥的异或
* @param state 变换数据
*/
void AddRoundKey(unsigned char state[][4], unsigned char k[][4]);
/**
* 逆 S 盒变换
* @param state 变换数据
*/
void InvSubBytes(unsigned char state[][4]);
/**
* 逆行变换
* @param state 变换数据
*/
void InvShiftRows(unsigned char state[][4]);
/**
* 逆列变换
* @param state 变换数据
*/
void InvMixColumns(unsigned char state[][4]);
};
```
# AES 实现文件
## CAES.cpp
```Cpp
#include "CAES.h"
#include <algorithm>
#include <fstream>
unsigned char Mul_01[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,
};
unsigned char Mul_02[256] = {
0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e,
0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e,
0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e,
0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e,0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e,
0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e,0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e,
0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae,0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe,
0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce,0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde,
0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee,0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe,
0x1b,0x19,0x1f,0x1d,0x13,0x11,0x17,0x15,0x0b,0x09,0x0f,0x0d,0x03,0x01,0x07,0x05,
0x3b,0x39,0x3f,0x3d,0x33,0x31,0x37,0x35,0x2b,0x29,0x2f,0x2d,0x23,0x21,0x27,0x25,
0x5b,0x59,0x5f,0x5d,0x53,0x51,0x57,0x55,0x4b,0x49,0x4f,0x4d,0x43,0x41,0x47,0x45,
0x7b,0x79,0x7f,0x7d,0x73,0x71,0x77,0x75,0x6b,0x69,0x6f,0x6d,0x63,0x61,0x67,0x65,
0x9b,0x99,0x9f,0x9d,0x93,0x91,0x97,0x95,0x8b,0x89,0x8f,0x8d,0x83,0x81,0x87,0x85,
0xbb,0xb9,0xbf,0xbd,0xb3,0xb1,0xb7,0xb5,0xab,0xa9,0xaf,0xad,0xa3,0xa1,0xa7,0xa5,
0xdb,0xd9,0xdf,0xdd,0xd3,0xd1,0xd7,0xd5,0xcb,0xc9,0xcf,0xcd,0xc3,0xc1,0xc7,0xc5,
0xfb,0xf9,0xff,0xfd,0xf3,0xf1,0xf7,0xf5,0xeb,0xe9,0xef,0xed,0xe3,0xe1,0xe7,0xe5
};
unsigned char Mul_03[256] = {
0x00,0x03,0x06,0x05,0x0c,0x0f,0x0a,0x09,0x18,0x1b,0x1e,0x1d,0x14,0x17,0x12,0x11,
0x30,0x33,0x36,0x35,0x3c,0x3f,0x3a,0x39,0x28,0x2b,0x2e,0x2d,0x24,0x27,0x22,0x21,
0x60,0x63,0x66,0x65,0x6c,0x6f,0x6a,0x69,0x78,0x7b,0x7e,0x7d,0x74,0x77,0x72,0x71,
0x50,0x53,0x56,0x55,0x5c,0x5f,0x5a,0x59,0x48,0x4b,0x4e,0x4d,0x44,0x47,0x42,0x41,
0xc0,0xc3,0xc6,0xc5,0xcc,0xcf,0xca,0xc9,0xd8,0xdb,0xde,0xdd,0xd4,0xd7,0xd2,0xd1,
0xf0,0xf3,0xf6,0xf5,0xfc,0xff,0xfa,0xf9,0xe8,0xeb,0xee,0xed,0xe4,0xe7,0xe2,0xe1,
0xa0,0xa3,0xa6,0xa5,0xac,0xaf,0xaa,0xa9,0xb8,0xbb,0xbe,0xbd,0xb4,0xb7,0xb2,0xb1,
0x90,0x93,0x96,0x95,0x9c,0x9f,0x9a,0x99,0x88,0x8b,0x8e,0x8d,0x84,0x87,0x82,0x81,
0x9b,0x98,0x9d,0x9e,0x97,0x94,0x91,0x92,0x83,0x80,0x85,0x86,0x8f,0x8c,0x89,0x8a,
0xab,0xa8,0xad,0xae,0xa7,0xa4,0xa1,0xa2,0xb3,0xb0,0xb5,0xb6,0xbf,0xbc,0xb9,0xba,
0xfb,0xf8,0xfd,0xfe,0xf7,0xf4,0xf1,0xf2,0xe3,0xe0,0xe5,0xe6,0xef,0xec,0xe9,0xea,
0xcb,0xc8,0xcd,0xce,0xc7,0xc4,0xc1,0xc2,0xd3,0xd0,0xd5,0xd6,0xdf,0xdc,0xd9,0xda,
0x5b,0x58,0x5d,0x5e,0x57,0x54,0x51,0x52,0x43,0x40,0x45,0x46,0x4f,0x4c,0x49,0x4a,
0x6b,0x68,0x6d,0x6e,0x67,0x64,0x61,0x62,0x73,0x70,0x75,0x76,0x7f,0x7c,0x79,0x7a,
0x3b,0x38,0x3d,0x3e,0x37,0x34,0x31,0x32,0x23,0x20,0x25,0x26,0x2f,0x2c,0x29,0x2a,
0x0b,0x08,0x0d,0x0e,0x07,0x04,0x01,0x02,0x13,0x10,0x15,0x16,0x1f,0x1c,0x19,0x1a
};
unsigned char Mul_09[256] = {
0x00,0x09,0x12,0x1b,0x24,0x2d,0x36,0x3f,0x48,0x41,0x5a,0x53,0x6c,0x65,0x7e,0x77,
0x90,0x99,0x82,0x8b,0xb4,0xbd,0xa6,0xaf,0xd8,0xd1,0xca,0xc3,0xfc,0xf5,0xee,0xe7,
0x3b,0x32,0x29,0x20,0x1f,0x16,0x0d,0x04,0x73,0x7a,0x61,0x68,0x57,0x5e,0x45,0x4c,
0xab,0xa2,0xb9,0xb0,0x8f,0x86,0x9d,0x94,0xe3,0xea,0xf1,0xf8,0xc7,0xce,0xd5,0xdc,
0x76,0x7f,0x64,0x6d,0x52,0x5b,0x40,0x49,0x3e,0x37,0x2c,0x25,0x1a,0x13,0x08,0x01,
0xe6,0xef,0xf4,0xfd,0xc2,0xcb,0xd0,0xd9,0xae,0xa7,0xbc,0xb5,0x8a,0x83,0x98,0x91,
0x4d,0x44,0x5f,0x56,0x69,0x60,0x7b,0x72,0x05,0x0c,0x17,0x1e,0x21,0x28,0x33,0x3a,
0xdd,0xd4,0xcf,0xc6,0xf9,0xf0,0xeb,0xe2,0x95,0x9c,0x87,0x8e,0xb1,0xb8,0xa3,0xaa,
0xec,0xe5,0xfe,0xf7,0xc8,0xc1,0xda,0xd3,0xa4,0xad,0xb6,0xbf,0x80,0x89,0x92,0x9b,
0x7c,0x75,0x6e,0x67,0x58,0x51,0x4a,0x43,0x34,0x3d,0x26,0x2f,0x10,0x19,0x02,0x0b,
0xd7,0xde,0xc5,0xcc,0xf3,0xfa,0xe1,0xe8,0x9f,0x96,0x8d,0x84,0xbb,0xb2,0xa9,0xa0,
0x47,0x4e,0x55,0x5c,0x63,0x6a,0x71,0x78,0x0f,0x06,0x1d,0x14,0x2b,0x22,0x39,0x30,
0x9a,0x93,0x88,0x81,0xbe,0xb7,0xac,0xa5,0xd2,0xdb,0xc0,0xc9,0xf6,0xff,0xe4,0xed,
0x0a,0x03,0x18,0x11,0x2e,0x27,0x3c,0x35,0x42,0x4b,0x50,0x59,0x66,0x6f,0x74,0x7d,
0xa1,0xa8,0xb3,0xba,0x85,0x8c,0x97,0x9e,0xe9,0xe0,0xfb,0xf2,0xcd,0xc4,0xdf,0xd6,
0x31,0x38,0x23,0x2a,0x15,0x1c,0x07,0x0e,0x79,0x70,0x6b,0x62,0x5d,0x54,0x4f,0x46
};
unsigned char Mul_0b[256] = {
0x00,0x0b,0x16,0x1d,0x2c,0x27,0x3a,0x31,0x58,0x53,0x4e,0x45,0x74,0x7f,0x62,0x69,
0xb0,0xbb,0xa6,0xad,0x9c,0x97,0x8a,0x81,0xe8,0xe3,0xfe,0xf5,0xc4,0xcf,0xd2,0xd9,
0x7b,0x70,0x6d,0x66,0x57,0x5c,0x41,0x4a,0x23,0x28,0x35,0x3e,0x0f,0x04,0x19,0x12,
0xcb,0xc0,0xdd,0xd6,0xe7,0xec,0xf1,0xfa,0x93,0x98,0x85,0x8e,0xbf,0xb4,0xa9,0xa2,
0xf6,0xfd,0xe0,0xeb,0xda,0xd1,0xcc,0xc7,0xae,0xa5,0xb8,0xb3,0x82,0x89,0x94,0x9f,
0x46,0x4d,0x50,0x5b,0x6a,0x61,0x7c,0x77,0x1e,0x15,0x08,0x03,0x32,0x39,0x24,0x2f,
0x8d,0x86,0x9b,0x90,0xa1,0xaa,0xb7,0xbc,0xd5,0xde,0xc3,0xc8,0xf9,0xf2,0xef,0xe4,
0x3d,0x36,0x2b,0x20,0x11,0x1a,0x07,0x0c,0x65,0x6e,0x73,0x78,0x49,0x42,0x5f,0x54,
0xf7,0xfc,0xe1,0xea,0xdb,0xd0,0xcd,0xc6,0xaf,0xa4,0xb9,0xb2,0x83,0x88,0x95,0x9e,
0x47,0x4c,0x51,0x5a,0x6b,0x60,0x7d,0x76,0x1f,0x14,0x09,0x02,0x33,0x38,0x25,0x2e,
0x8c,0x87,0x9a,0x91,0xa0,0xab,0xb6,0xbd,0xd4,0xdf,0xc2,0xc9,0xf8,0xf3,0xee,0xe5,
0x3c,0x37,0x2a,0x21,0x10,0x1b,0x06,0x0d,0x64,0x6f,0x72,0x79,0x48,0x43,0x5e,0x55,
0x01,0x0a,0x17,0x1c,0x2d,0x26,0x3b,0x30,0x59,0x52,0x4f,0x44,0x75,0x7e,0x63,0x68,
0xb1,0xba,0xa7,0xac,0x9d,0x96,0x8b,0x80,0xe9,0xe2,0xff,0xf4,0xc5,0xce,0xd3,0xd8,
0x7a,0x71,0x6c,0x67,0x56,0x5d,0x40,0x4b,0x22,0x29,0x34,0x3f,0x0e,0x05,0x18,0x13,
0xca,0xc1,0xdc,0xd7,0xe6,0xed,0xf0,0xfb,0x92,0x99,0x84,0x8f,0xbe,0xb5,0xa8,0xa3
};
unsigned char Mul_0d[256] = {
0x00,0x0d,0x1a,0x17,0x34,0x39,0x2e,0x23,0x68,0x65,0x72,0x7f,0x5c,0x51,0x46,0x4b,
0xd0,0xdd,0xca,0xc7,0xe4,0xe9,0xfe,0xf3,0xb8,0xb5,0xa2,0xaf,0x8c,0x81,0x96,0x9b,
0xbb,0xb6,0xa1,0xac,0x8f,0x82,0x95,0x98,0xd3,0xde,0xc9,0xc4,0xe7,0xea,0xfd,0xf0,
0x6b,0x66,0x71,0x7c,0x5f,0x52,0x45,0x48,0x03,0x0e,0x19,0x14,0x37,0x3a,0x2d,0x20,
0x6d,0x60,0x77,0x7a,0x59,0x54,0x43,0x4e,0x05,0x08,0x1f,0x12,0x31,0x3c,0x2b,0x26,
0xbd,0xb0,0xa7,0xaa,0x89,0x84,0x93,0x9e,0xd5,0xd8,0xcf,0xc2,0xe1,0xec,0xfb,0xf6,
0xd6,0xdb,0xcc,0xc1,0xe2,0xef,0xf8,0xf5,0xbe,0xb3,0xa4,0xa9,0x8a,0x87,0x90,0x9d,
0x06,0x0b,0x1c,0x11,0x32,0x3f,0x28,0x25,0x6e,0x63,0x74,0x79,0x5a,0x57,0x40,0x4d,
0xda,0xd7,0xc0,0xcd,0xee,0xe3,0xf4,0xf9,0xb2,0xbf,0xa8,0xa5,0x86,0x8b,0x9c,0x91,
0x0a,0x07,0x10,0x1d,0x3e,0x33,0x24,0x29,0x62,0x6f,0x78,0x75,0x56,0x5b,0x4c,0x41,
0x61,0x6c,0x7b,0x76,0x55,0x58,0x4f,0x42,0x09,0x04,0x13,0x1e,0x3d,0x30,0x27,0x2a,
0xb1,0xbc,0xab,0xa6,0x85,0x88,0x9f,0x92,0xd9,0xd4,0xc3,0xce,0xed,0xe0,0xf7,0xfa,
0xb7,0xba,0xad,0xa0,0x83,0x8e,0x99,0x94,0xdf,0xd2,0xc5,0xc8,0xeb,0xe6,0xf1,0xfc,
0x67,0x6a,0x7d,0x70,0x53,0x5e,0x49,0x44,0x0f,0x02,0x15,0x18,0x3b,0x36,0x21,0x2c,
0x0c,0x01,0x16,0x1b,0x38,0x35,0x22,0x2f,0x64,0x69,0x7e,0x73,0x50,0x5d,0x4a,0x47,
0xdc,0xd1,0xc6,0xcb,0xe8,0xe5,0xf2,0xff,0xb4,0xb9,0xae,0xa3,0x80,0x8d,0x9a,0x97
};
unsigned char Mul_0e[256] = {
0x00,0x0e,0x1c,0x12,0x38,0x36,0x24,0x2a,0x70,0x7e,0x6c,0x62,0x48,0x46,0x54,0x5a,
0xe0,0xee,0xfc,0xf2,0xd8,0xd6,0xc4,0xca,0x90,0x9e,0x8c,0x82,0xa8,0xa6,0xb4,0xba,
0xdb,0xd5,0xc7,0xc9,0xe3,0xed,0xff,0xf1,0xab,0xa5,0xb7,0xb9,0x93,0x9d,0x8f,0x81,
0x3b,0x35,0x27,0x29,0x03,0x0d,0x1f,0x11,0x4b,0x45,0x57,0x59,0x73,0x7d,0x6f,0x61,
0xad,0xa3,0xb1,0xbf,0x95,0x9b,0x89,0x87,0xdd,0xd3,0xc1,0xcf,0xe5,0xeb,0xf9,0xf7,
0x4d,0x43,0x51,0x5f,0x75,0x7b,0x69,0x67,0x3d,0x33,0x21,0x2f,0x05,0x0b,0x19,0x17,
0x76,0x78,0x6a,0x64,0x4e,0x40,0x52,0x5c,0x06,0x08,0x1a,0x14,0x3e,0x30,0x22,0x2c,
0x96,0x98,0x8a,0x84,0xae,0xa0,0xb2,0xbc,0xe6,0xe8,0xfa,0xf4,0xde,0xd0,0xc2,0xcc,
0x41,0x4f,0x5d,0x53,0x79,0x77,0x65,0x6b,0x31,0x3f,0x2d,0x23,0x09,0x07,0x15,0x1b,
0xa1,0xaf,0xbd,0xb3,0x99,0x97,0x85,0x8b,0xd1,0xdf,0xcd,0xc3,0xe9,0xe7,0xf5,0xfb,
0x9a,0x94,0x86,0x88,0xa2,0xac,0xbe,0xb0,0xea,0xe4,0xf6,0xf8,0xd2,0xdc,0xce,0xc0,
0x7a,0x74,0x66,0x68,0x42,0x4c,0x5e,0x50,0x0a,0x04,0x16,0x18,0x32,0x3c,0x2e,0x20,
0xec,0xe2,0xf0,0xfe,0xd4,0xda,0xc8,0xc6,0x9c,0x92,0x80,0x8e,0xa4,0xaa,0xb8,0xb6,
0x0c,0x02,0x10,0x1e,0x34,0x3a,0x28,0x26,0x7c,0x72,0x60,0x6e,0x44,0x4a,0x58,0x56,
0x37,0x39,0x2b,0x25,0x0f,0x01,0x13,0x1d,0x47,0x49,0x5b,0x55,0x7f,0x71,0x63,0x6d,
0xd7,0xd9,0xcb,0xc5,0xef,0xe1,0xf3,0xfd,0xa7,0xa9,0xbb,0xb5,0x9f,0x91,0x83,0x8d
};
CAES::CAES(const char* key)
{
unsigned char sBox[] =
{ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, /*0*/
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, /*1*/
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, /*2*/
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, /*3*/
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, /*4*/
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, /*5*/
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, /*6*/
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, /*7*/
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, /*8*/
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, /*9*/
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, /*a*/
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, /*b*/
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, /*c*/
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, /*d*/
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, /*e*/
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16 /*f*/
};
unsigned char invsBox[256] =
{ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb, /*0*/
0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb, /*1*/
0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e, /*2*/
0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25, /*3*/
0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92, /*4*/
0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84, /*5*/
0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06, /*6*/
0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b, /*7*/
0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73, /*8*/
0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e, /*9*/
0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b, /*a*/
0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4, /*b*/
0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f, /*c*/
0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef, /*d*/
0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61, /*e*/
0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d /*f*/
};
memcpy(Sbox, sBox, 256);
memcpy(InvSbox, invsBox, 256);
KeyExpansion(key);
}
CAES::~CAES()
{
}
void CAES::Xor(unsigned char* in, int len)
{
for (int i = 0; i < len; i++)
in[i] ^= w[i%11][0][0];
}
void CAES::Encrypt(unsigned char* data)
{
unsigned char state[4][4];
int i, r, c;
for (r = 0; r < 4; r++)
{
for (c = 0; c < 4; c++)
{
state[r][c] = data[c * 4 + r];
}
}
AddRoundKey(state, w[0]);
for (i = 1; i <= 10; i++)
{
SubBytes(state);
ShiftRows(state);
if (i != 10)MixColumns(state);
AddRoundKey(state, w[i]);
}
for (r = 0; r < 4; r++)
{
for (c = 0; c < 4; c++)
{
data[c * 4 + r] = state[r][c];
}
}
}
void CAES::Decrypt(unsigned char* data)
{
unsigned char state[4][4];
int i, r, c;
for (r = 0; r < 4; r++)
{
for (c = 0; c < 4; c++)
{
state[r][c] = data[c * 4 + r];
}
}
AddRoundKey(state, w[10]);
for (i = 9; i >= 0; i--)
{
InvShiftRows(state);
InvSubBytes(state);
AddRoundKey(state, w[i]);
if (i)
{
InvMixColumns(state);
}
}
for (r = 0; r < 4; r++)
{
for (c = 0; c < 4; c++)
{
data[c * 4 + r] = state[r][c];
}
}
}
void* CAES::Encrypt(void* in, int inlen, int& outlen, bool fill)
{
outlen = inlen;
if (fill && inlen % 16 > 0)
outlen += 16 - (inlen % 16);
unsigned char* data = new unsigned char[outlen];
memset(data, 0x0, outlen);
memcpy(data, in, inlen);
for (int i = 0; i < inlen; i += 16)
{
// 不足16位的用异或加密
if (outlen - i < 16)
Xor(data + i, outlen - i);
else
Encrypt(data + i);
}
return (void*)data;
}
void* CAES::Decrypt(void* in, int inlen, int& outlen)
{
outlen = inlen;
unsigned char* data = new unsigned char[outlen];
memset(data, 0x0, outlen);
memcpy(data, in, inlen);
for (int i = 0; i < outlen; i += 16)
{
if (outlen - i < 16)
Xor(data + i, outlen - i);
else
Decrypt(data + i);
}
return (void*)data;
}
void CAES::KeyExpansion(const char* key)
{
int i, j, r, c;
unsigned char rc[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
for (r = 0; r < 4; r++)
{
for (c = 0; c < 4; c++)
{
w[0][r][c] = key[r + c * 4];
}
}
for (i = 1; i <= 10; i++)
{
for (j = 0; j < 4; j++)
{
unsigned char t[4];
for (r = 0; r < 4; r++)
{
t[r] = j ? w[i][r][j - 1] : w[i - 1][r][3];
}
if (j == 0)
{
unsigned char temp = t[0];
for (r = 0; r < 3; r++)
{
t[r] = Sbox[t[(r + 1) % 4]];
}
t[3] = Sbox[temp];
t[0] ^= rc[i - 1];
}
for (r = 0; r < 4; r++)
{
w[i][r][j] = w[i - 1][r][j] ^ t[r];
}
}
}
}
void CAES::SubBytes(unsigned char state[][4])
{
int r, c;
for (r = 0; r < 4; r++)
{
for (c = 0; c < 4; c++)
{
state[r][c] = Sbox[state[r][c]];
}
}
}
void CAES::ShiftRows(unsigned char state[][4])
{
unsigned char t[4];
int r, c;
for (r = 1; r < 4; r++)
{
for (c = 0; c < 4; c++)
{
t[c] = state[r][(c + r) % 4];
}
for (c = 0; c < 4; c++)
{
state[r][c] = t[c];
}
}
}
void CAES::MixColumns(unsigned char state[][4])
{
unsigned char t[4];
int r, c;
for (c = 0; c < 4; c++)
{
for (r = 0; r < 4; r++)
{
t[r] = state[r][c];
}
for (r = 0; r < 4; r++)
{
state[r][c] = Mul_02[t[r]]
^ Mul_03[t[(r + 1) % 4]]
^ Mul_01[t[(r + 2) % 4]]
^ Mul_01[t[(r + 3) % 4]];
}
}
}
void CAES::AddRoundKey(unsigned char state[][4], unsigned char k[][4])
{
int r, c;
for (c = 0; c < 4; c++)
{
for (r = 0; r < 4; r++)
{
state[r][c] ^= k[r][c];
}
}
}
void CAES::InvSubBytes(unsigned char state[][4])
{
int r, c;
for (r = 0; r < 4; r++)
{
for (c = 0; c < 4; c++)
{
state[r][c] = InvSbox[state[r][c]];
}
}
}
void CAES::InvShiftRows(unsigned char state[][4])
{
unsigned char t[4];
int r, c;
for (r = 1; r < 4; r++)
{
for (c = 0; c < 4; c++)
{
t[c] = state[r][(c - r + 4) % 4];
}
for (c = 0; c < 4; c++)
{
state[r][c] = t[c];
}
}
}
void CAES::InvMixColumns(unsigned char state[][4])
{
unsigned char t[4];
int r, c;
for (c = 0; c < 4; c++)
{
for (r = 0; r < 4; r++)
{
t[r] = state[r][c];
}
for (r = 0; r < 4; r++)
{
state[r][c] = Mul_0e[t[r]]
^ Mul_0b[t[(r + 1) % 4]]
^ Mul_0d[t[(r + 2) % 4]]
^ Mul_09[t[(r + 3) % 4]];
}
}
}
```
# 测试
## main.cpp
```Cpp
#include "CAES.h"
#include <iostream>
#include <io.h>
void printf2char(const char* data, int len) {
for (int i = 0; i < len; i++)
{
std::cout << std::hex << static_cast<unsigned int>(static_cast<unsigned char>(data[i])) << ' ';
}
std::cout << std::endl;
}
int main(int argc, char **argv)
{
CAES* aes = new CAES("1234567890abcdef");
char str[] = "guoke3915";
printf2char(str, strlen(str) + 1);
int encLen = 0;
char* enc = (char*)aes->Encrypt(str, strlen(str)+1, encLen, true);
printf2char(enc, encLen);
int decLen = 0;
char* dec = (char*)aes->Decrypt(enc, encLen, decLen);
printf2char(dec, decLen);
return 0;
}
```

@ -0,0 +1,28 @@
---
icon: edit
date: 2023-03-17
category:
- 系统配置
tag:
- cmd
- 路径
headerDepth: 5
---
# CMD 获取当前脚本各种路径
```cmd
@echo off
echo 当前盘符:%~d0
echo 当前盘符和路径:%~dp0
echo 当前批处理全路径:%~f0
echo 当前盘符和路径的短文件名格式:%~sdp0
echo 当前CMD默认目录%cd%
echo 目录中有空格也可以加入""避免找不到路径
echo 当前盘符:"%~d0"
echo 当前盘符和路径:"%~dp0"
echo 当前批处理全路径:"%~f0"
echo 当前盘符和路径的短文件名格式:"%~sdp0"
echo 当前CMD默认目录"%cd%"
pause
```

@ -0,0 +1,129 @@
---
icon: edit
date: 2022-10-25
category:
- 系统配置
- Linux
headerDepth: 5
---
# Centos7 防火墙
#### 安装:
yum install firewalld
#### 1、firewalld的基本使用
启动: systemctl start firewalld
查看状态: systemctl status firewalld
禁用,禁止开机启动: systemctl disable firewalld
停止运行: systemctl stop firewalld
#### 2.配置firewalld-cmd
查看版本: firewall-cmd --version
查看帮助: firewall-cmd --help
显示状态: firewall-cmd --state
查看所有打开的端口: firewall-cmd --zone=public --list-ports
更新防火墙规则: firewall-cmd --reload
更新防火墙规则,重启服务: firewall-cmd --completely-reload
查看已激活的Zone信息: firewall-cmd --get-active-zones
查看指定接口所属区域: firewall-cmd --get-zone-of-interface=eth0
拒绝所有包firewall-cmd --panic-on
取消拒绝状态: firewall-cmd --panic-off
查看是否拒绝: firewall-cmd --query-panic
#### 3.信任级别通过Zone的值指定
drop: 丢弃所有进入的包,而不给出任何响应
block: 拒绝所有外部发起的连接,允许内部发起的连接
public: 允许指定的进入连接
external: 同上,对伪装的进入连接,一般用于路由转发
dmz: 允许受限制的进入连接
work: 允许受信任的计算机被限制的进入连接,类似 workgroup
home: 同上,类似 homegroup
internal: 同上,范围针对所有互联网用户
trusted: 信任所有连接
#### 4.firewall开启和关闭端口
以下都是指在public的zone下的操作不同的Zone只要改变Zone后面的值就可以
自媒体培训
添加: firewall-cmd --zone=public --add-port=80/tcp --permanent --permanent永久生效没有此参数重启后失效
重新载入: firewall-cmd --reload
查看: firewall-cmd --zone=public --query-port=80/tcp
删除: firewall-cmd --zone=public --remove-port=80/tcp --permanent
#### 5.管理服务
以smtp服务为例 添加到work zone
添加: firewall-cmd --zone=work --add-service=smtp
查看: firewall-cmd --zone=work --query-service=smtp
删除: firewall-cmd --zone=work --remove-service=smtp
#### 6.配置 IP 地址伪装
查看: firewall-cmd --zone=external --query-masquerade
打开: firewall-cmd --zone=external --add-masquerade
关闭: firewall-cmd --zone=external --remove-masquerade
#### 7.端口转发
打开端口转发首先需要打开IP地址伪装 firewall-cmd --zone=external --add-masquerade
转发 tcp 22 端口至 3753 firewall-cmd --zone=external --add-forward-port=22:porto=tcp:toport=3753
转发端口数据至另一个IP的相同端口 firewall-cmd --zone=external --add-forward-port=22:porto=tcp:toaddr=192.168.1.112
转发端口数据至另一个IP的 3753 端口: firewall-cmd --zone=external --add-forward-port=22:porto=tcp:toport=3753:toaddr=192.168.1.112
#### 8.systemctl是CentOS7的服务管理工具中主要的工具它融合之前service和chkconfig的功能于一体。
启动一个服务systemctl start firewalld.service
关闭一个服务systemctl stop firewalld.service
重启一个服务systemctl restart firewalld.service
显示一个服务的状态systemctl status firewalld.service
在开机时启用一个服务systemctl enable firewalld.service
在开机时禁用一个服务systemctl disable firewalld.service
查看服务是否开机启动systemctl is-enabled firewalld.service
查看已启动的服务列表systemctl list-unit-files|grep enabled
查看启动失败的服务列表systemctl --failed

@ -0,0 +1,24 @@
---
icon: edit
date: 2023-03-17
category:
- 系统配置
- DDE
headerDepth: 5
---
# DDE 动态数据交换 相关技术文档
DDE 相关技术文档
## 关于动态数据Exchange
Windows提供了几种在应用程序之间传输数据的方法。 一种方法是使用动态数据Exchange (DDE) 协议。 DDE 协议是一组消息和准则。 它在共享数据的应用程序之间发送消息,并使用共享内存在应用程序之间交换数据。 应用程序可以使用 DDE 协议进行一次性数据传输和连续交换,应用程序在新的数据可用时将更新发送到彼此。
Windows还支持动态数据Exchange管理库 (DDEML) 。 DDEML 是一个动态链接库, (DLL) 应用程序可用于共享数据。 DDEML 提供函数和消息,用于简化向应用程序添加 DDE 功能的任务。 应用程序使用 DDEML 函数来管理 DDE 对话,而不是直接发送、发布和处理 DDE 消息。 (DDE 对话是客户端和服务器应用程序之间的交互。)
DDEML 还提供用于管理 DDE 应用程序共享的字符串和数据的工具。 DDE 应用程序创建和交换字符串句柄(标识字符串)和数据句柄,而不是使用原子和指向共享内存对象的指针。 DDEML 还使服务器应用程序能够注册它支持的服务名称。 这些名称将广播到系统中的其他应用程序,这些应用程序可以使用名称连接到服务器。 此外DDEML 通过强制 DDE 应用程序以一致的方式实现 DDE 协议,确保 DDE 应用程序之间的兼容性。
使用基于消息的 DDE 协议的现有应用程序与使用 DDEML 的应用程序完全兼容。 也就是说,使用基于消息的 DDE 的应用程序可以建立对话,并与使用 DDEML 的应用程序执行事务。 由于 DDEML 的许多优点,新应用程序应使用它而不是 DDE 消息。 若要使用 DDEML 的 API 元素,必须在源文件中包含 DDEML 头文件、链接到 DDEML 库,并确保 DDEML 动态链接库位于系统的搜索路径中。
微软官方介绍文档 [关于动态数据Exchange](https://learn.microsoft.com/zh-cn/windows/win32/dataxchg/about-dynamic-data-exchange)
微软官方api文档 [动态数据交换](https://learn.microsoft.com/zh-cn/windows/win32/api/_dataxchg/)

@ -0,0 +1,27 @@
---
icon: edit
date: 2022-12-15
category:
- 系统配置
- Linux
- 网站搭建
tag:
- nip.io
- 域名
headerDepth: 5
---
# DNS泛域名解析应用nip.io/sslip.io直接通过nip.io域名拼接ip地址的方式直接解析到指定ip
使用 nip.io 作为k8s的入口 域名解析。 nip.io 是一个免费的域名解析服务可以将符合下列格式的域名解析对应的ip可用来作为应用路由的解析服务省去配置本地 hosts 文件的步骤。
格式
```
10.0.0.1.nip.io maps to 10.0.0.1
app.10.0.0.1.nip.io maps to 10.0.0.1
customer1.app.10.0.0.1.nip.io maps to 10.0.0.1
customer2.app.10.0.0.1.nip.io maps to 10.0.0.1
otherapp.10.0.0.1.nip.io maps to 10.0.0.1
```
例如Ingress IP 地址为 139.198.121.154在创建应用路由时Hostname 一栏填写为 demo.139.198.121.154.nip.io其它保持原来的设置。
sslip.io 也是一种类似域名解析服务使SSL证书生成更加容易。

@ -0,0 +1,26 @@
---
icon: edit
date: 2022-10-17
category:
- Docker
headerDepth: 5
---
# Docker 安装 minio
```
docker run -d --name minio \
-p 9000:9000 \
-p 9001:9001 \
--restart=always \
-e MINIO_ACCESS_KEY=minio \
-e MINIO_SECRET_KEY=minio123 \
-e "MINIO_BROWSER_REDIRECT_URL=https://local.wuanwanghao.top:9001" \
-e "MINIO_SERVER_URL=https://local.wuanwanghao.top:9000" \
-v /home/wanghao/minio/config:/root/.minio \
-v /home/wanghao/minio/data1:/data1 \
-v /home/wanghao/minio/data2:/data2 \
-v /home/wanghao/minio/data3:/data3 \
-v /home/wanghao/minio/data4:/data4 \
minio/minio server /data{1...4} --console-address ":9001" -address ":9000"
```

@ -0,0 +1,118 @@
---
icon: edit
date: 2021-09-15
category:
- Docker
tag:
- Docker
- mysql
headerDepth: 5
---
# Docker 安装mysql8.0
### 一、写在前面
今天自己原本的mysql服务配置出了问题刚好自己接触了容器技术就想着自己使用docker重新部署一个mysql服务。
### 二、下载步骤
首先要获取mysql镜像可以通过官网下载或者从公司的仓库获取下面演示从官网下载步骤
#### 2.1 docker search mysql可以看到搜索的结果这个结果是按照一定的星级评价规则排序的。
![image.png](/upload/2021/09/image-6acf16e6457a48e49d80b7b1e6561073.png)
#### 2.2 docker pull mysql 拉取一个合适版本的mysql到本地服务器
### 三、启动镜像
```txt
-p 3307:3306将容器的3307端口映射到主机的3306端口
-v $PWD/mysql:/var/lib/mysql将主机当前目录下的/mysql挂载到容器的/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456初始化root用户的密码
name 给容器命名test_mysql
-d 表示刚下载的镜像id
```
命令行如下:
```shell
docker run \
-p 3307:3306 \
--name mysql_3307 \
--privileged=true \
-v /wanghao/mysql_3307/conf.d:/etc/mysql/conf.d \
-v /wanghao/mysql_3307/logs:/logs \
-v /wanghao/mysql_3307/data:/var/lib/mysql \
-v /etc/localtime:/etc/localtime \
-v /wanghao/mysql_3307/mysql-files:/var/lib/mysql-files \
-e MYSQL_ROOT_PASSWORD=123456 \
-d mysql
```
### 四、局域网无法访问数据库的方法
```sql
create user 'wanghao'@'%' identified with mysql_native_password by 'Wh*123456';
grant all privileges on *.* to 'wanghao'@'%';
```
注意这里platform可以任意命名表示赋予这个账户的权限这里是赋予所有的权限
```sql
update user set host='%' where user='root';
alter user 'root'@'%' identified with mysql_native_password by 'root';
```
刷新权限:
```sql
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
```
### 五、表名大小写问题
![image.png](/upload/2021/10/image-c13812355983466f952a08f36c406b63.png)
MySQL 上了 8 后,在 Linux 端,对于 lower_case_table_names 参数,只能在初始化的时候设置了,若初始化的时候没设置,那后面就傻愣愣了
示例:
当前本地已有环境设置为 lower_case_table_names = 1 了,将 lower_case_table_names 修改为 0 会发生什么。
测试版本
```shell
root [(none)]> select version();
+-----------+
| version() |
+-----------+
| 8.0.18 |
+-----------+
1 row in set (0.00 sec)
```
lower_case_table_names不是动态参数将my.cnf 中 lower_case_table_names 改为 0
重启 mysql
查看错误日志
```log
2020-09-22T17:16:49.781973+08:00 1 [ERROR] [MY-011087] [Server] Different lower_case_table_names settings for server ('0') and data dictionary ('1').
2020-09-22T17:16:49.782401+08:00 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed.
2020-09-22T17:16:49.782620+08:00 0 [ERROR] [MY-010119] [Server] Aborting
```
官方是这么说的
地址https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html
![image.png](https://pic4.zhimg.com/v2-7f96160724c66388120bafc3ff3f6d1b_r.jpg)
所以,除非你是安装在 windows上或者可以确保开发人员实行规范建表等操作不然就在初始化配置my.cnf时候就将 lower_case_table_names = 1 配置上去吧
#### docker 部署要大小写忽略只能 运行容器命令的时候加上了
```shell
docker run \
-p 3307:3306 \
--name mysql_3307 \
--privileged=true \
-v /wanghao/mysql_3307/conf.d:/etc/mysql/conf.d \
-v /wanghao/mysql_3307/logs:/logs \
-v /wanghao/mysql_3307/data:/var/lib/mysql \
-v /etc/localtime:/etc/localtime \
-v /wanghao/mysql_3307/mysql-files:/var/lib/mysql-files \
-e MYSQL_ROOT_PASSWORD=123456 \
-d mysql --lower-case-table-names=1
```

@ -0,0 +1,100 @@
---
icon: edit
date: 2021-09-16
category:
- Docker
tag:
- Docker
- nginx
headerDepth: 5
---
# Docker给nginx添加端口映射
## 场景:
>运行了nginx一开始只映射了80端口后面载部署项目的时候需要用到其他端口不想重新部署容器所以通过修改配置文件的方式给容器添加其他端口
>当然。添加端口的方法是通用的,除此以外的方法比如将容器打包成镜像,再运行一个容器,或者干脆放弃当前容器,重新运行一个容器是完全不在我考虑范围内的
## 1、查看容器ID
执行命令
```shell
docker inspect nginx # 容器名
```
输出
```json
[
{
"Id": "135254e3429d1e75aa68569137c753b789416256f2ced52b4c5a85ec3849db87", # hash_of_the_container
"Created": "2020-08-21T09:41:36.597993005Z",
"Path": "/docker-entrypoint.sh",
"Args": [
"nginx",
"-g",
"daemon off;"
],
"State": {
...
```
## 2、修改之前一定要先停掉容器否则自动还原
```shell
docker stop nginx
```
## 3、修改配置文件
修改hostconfig.json
```shell
cd /var/lib/docker/containers/135254e3429d1e75aa68569137c753b789416256f2ced52b4c5a85ec3849db87 # container id
vim hostconfig.json
```
找到端口绑定,原本内容:
![image.png](/upload/2021/09/image-b18afbfb43414f6da5550bae5f7566c0.png)
照猫画虎,添加端口
```json
"PortBindings": {
"80/tcp": [
{
"HostIp": "",
"HostPort": "80"
}
],
"8080/tcp": [
{
"HostIp": "",
"HostPort": "8080"
}
],
"8189/tcp": [
{
"HostIp": "",
"HostPort": "8189"
}
]
},
```
修改config.v2.json
同路径下打开config.v2.json修改:ExposedPorts
```json
"ExposedPorts": {
"80/tcp": {},
"8080/tcp": {},
"8189/tcp": {}
},
... # 略
```
### 注意
很多文章中提到还要修改Ports实际上是不需要的只有在你没有stop容器时Ports才会有值如果关闭了容器就是null。当然如果你修改了也无所谓因为重启容器后就会被刷新。
## 4、保存、退出、重启容器
```shell
sudo systemctl restart docker.service # 重启docker服务
docker start nginx # 容器名 # 启动容器
```

@ -0,0 +1,70 @@
---
icon: edit
date: 2023-03-31
category:
- .Net
tag:
- EF Core
- dotnet-cli
headerDepth: 5
---
# EF Core 工具 命令行工具-非包管理器的控制台工具Entity Framework Core tools reference - .NET Core CLI
### 安装工具
```shell
dotnet tool install --global dotnet-ef
```
若要将它用作本地工具,请使用工具清单文件恢复声明为工具依赖项的项目的依赖项。
使用下列命令更新工具:
```shell
dotnet tool update --global dotnet-ef
```
在将工具用于特定项目之前,需要将 Microsoft.EntityFrameworkCore.Design 添加到该项目中。
```shell
dotnet add package Microsoft.EntityFrameworkCore.Design
```
### 验证安装
运行以下命令,验证是否已正确安装 EF Core CLI 工具:
```shell
dotnet ef
```
命令的输出标识使用的工具版本:
```shell
_/\__
---==/ \\
___ ___ |. \|\
| __|| __| | ) \\\
| _| | _| \_/ | //|\\
|___||_| / \\\/\\
Entity Framework Core .NET Command-line Tools 7.0.3
Usage: dotnet ef [options] [command]
Options:
--version Show version information
-h|--help Show help information
-v|--verbose Show verbose output.
--no-color Don't colorize output.
--prefix-output Prefix output with level.
Commands:
database Commands to manage the database.
dbcontext Commands to manage DbContext types.
migrations Commands to manage migrations.
```
更新工具
使用 ```dotnet tool update --global dotnet-ef``` 将全局工具更新到最新的可用版本。 如果在项目中本地安装了这些工具,请使用 ```dotnet tool update dotnet-ef。``` 通过将 --version <VERSION> 追加到命令来安装特定版本。 有关更多详细信息,请参阅 dotnet 工具文档的更新部分。
更多用法参考官方文档 [Entity Framework Core 工具参考 - .NET Core CLI](https://learn.microsoft.com/zh-cn/ef/core/cli/dotnet)

@ -0,0 +1,118 @@
---
icon: edit
date: 2021-09-17
category:
- 内网穿透
tag:
- frp
headerDepth: 5
---
# FRP 简单入门安装配置教程 - 开源免费内网穿透工具,无公网 IP 远程访问
虽然现在宽带速度都很快,但对于电脑玩家来说,最大的问题是 **“没有公网 IP”** 这使得想要在外访问家里的电脑、NAS、树莓派、摄像头等网络设备或远程控制等都无法轻松实现。
这时你就需要一款**内网穿透工具**来让外网与你家内网建立起连接,实现无公网 IP 的远程访问了。 **「Frp」** 是一款流行的跨平台开源免费内网穿透工具,支持 Windows、macOS 与 Linux。你只需一台快速稳定的 VPS 服务器即可愉快地进行内网穿透,实现家中设备公网直接访问了……
> ### 安装 FRP 需要准备的材料:
很多地方宽带都已不再提供**公网 IP** 了,如果你想家里的设备如 NAS、电脑可在外网访问那么只能通过内网穿透工具实现。考虑到安全和稳定性最优方案是买一台 VPS 服务器用于内网穿透。现在正好赶上双11其中「**阿里云双11活动**」非常给力!**腾讯云、Vultr** 也值得考虑。
在内网也需要一台机器用于运行 Frp 的客户端,可以是 Windows 电脑、Mac或者是树莓派、NAS 等 Linux 设备。
市面上也有其他方案,比如花生壳相关软硬件产品,免费限制很多,付费价格贵,浪不起来。其他小公司的产品安全性又无法保证,那还不如自己买 VPS 建一个,有自己的服务器,日后各种建站的玩法还更多更实用,还能顺便学学 Linux 呢。
> ### 什么是 Frp
段落引用内网穿透工具有很多,其中 Frp (Fast Reverse Proxy) 是比较流行的一款。FRP 是一个免费开源的用于内网穿透的反向代理应用,它支持 TCP、UDP 协议, 也为 http 和 https 协议提供了额外的支持。你可以粗略理解它是一个中转站,帮你实现 ```公网 ←→ FRP(服务器) ←→ 家庭内网 的连接```,让内网里的设备也可以被公网访问到。
![](https://img.iplaysoft.com/wp-content/uploads/2019/frp/frp_architecture.png!0x0.webp)
<center>官方提供的 Frp 架构原理示意图</center>
而目前 FRP 还推出了“点对点穿透”的试验性功能,连接成功后可以让公网设备直接跟内网设备“点对点”传输,数据流不再经过 VPS 中转,这样可以不受服务器带宽的限制,传输大文件会更快更稳定。当然,此功能并不能保证在你的网络环境 100% 可用,而且还要求访问端也得运行 FRP 客户端 (因此目前手机是无法实现的,只有电脑可以)。由于实现条件较多,所以有文件传输需求的朋友还是建议买带宽稍大一点的 VPS 会比较省心。
> ### 简单的 Frp 安装配置教程:
现在假设你已经有一台 VPS 服务器了,那么只需按照下面的步骤,一步一步来来即可搞定 FRP 的安装和配置。当然,这里涉及到一些 Linux 基础操作命令如果完全未接触过的朋友可以找一些「Linux 入门教程」先了解一下。
> ### 1、服务器端安装配置 Frp
FRP 使用 Go 语言开发,可以支持 Windows、Linux、macOS、ARM 等多平台部署。FRP 安装非常容易,只需下载对应系统平台的软件包并解压就可用了。这里以 Linux 系统为例:
``` shell
export FRP_VERSION=0.29.1
sudo mkdir -p /etc/frp
cd /etc/frp
sudo wget "https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_linux_amd64.tar.gz"
sudo tar xzvf frp_${FRP_VERSION}_linux_amd64.tar.gz
sudo mv frp_${FRP_VERSION}_linux_amd64/* /etc/frp
```
其中,第一行等号后面的``` 0.29.1``` 是 frp 的版本号 (截稿为止最新版本)。你安装的时候可以到官网查看下有没更新的版本,只需将新版本的号码替换掉 ```0.29.1``` 即可。
FRP 默认提供了 2 个服务端配置文件,一个是简化版的 ```frps.ini```,另一个是完整版的 ```frps_full.ini```。初学者只需用简版配置即可,在简版 ```frps.ini``` 配置文件里,默认设置了监听端口为 ```7000```,你可以按需修改它。
>#### 防火墙和安全组开放指定的端口:
请一定要记住,你需要将服务器的系统防火土啬,以及阿里云、腾讯云后台里找到“安全组策略”的相关配置,设置 ```7000``` 或你修改过的对应端口的「<Font color = 'red'>允许入站和出站 </font>」,否则会一直连接不上的哦!!!这个切记!!
>#### 启动 FRP 服务端
``` shell
./frps -c ./frps.ini
```
如服务器使用 Win 系统,假设解压到 ```c:\frp``` 文件夹,那么只需这样启动:
``` shell
c:\frp\frps.exe -c c:\frp\frps.exe
```
2、配置 Frp 客户端 (安装在内网的机器上)
设置好服务器上 Frp 服务端后,我们就需要在内网的机器上安装 Frp 的客户端了。 Frp 的客户端程序 frpc (frpc.exe) 与服务器端都在同一个压缩包里, 我们同样下载对应系统版本的软件包。
你可以将 Frp 客户端安装在内网的 Windows 电脑、Linux 设备 (比如树莓派) 或者 NAS甚至部分路由器等设备上。Linux 客户端的安装和启动与服务器端没有太多区别,只是对应运行程序是 frp<Font color = 'red'>c</font> 而不是 frp<Font color = 'red'>s</font>
为了简单起见,我们这里以 Windows 电脑来安装 Frp 客户端,因为 Frp 是绿色程序,下载软件包回来解压后,启动 ```frpc.exe``` 即可。
但在启动前我们需要先修改配置文件我们以配置“Windows 远程桌面控制”以及“群晖 NAS 管理界面”为例。假设你的 FRP 服务端所在的 VPS 公网 IP 为 ```1.2.3.4``` 而客户端是 Win 电脑,我们来修改 ```frpc.ini``` 配置文件:
``` ini
[common]
# server_addr 为 FRP 服务端 (VPS 服务器) 的公网 IP
server_addr = 1.2.3.4
server_port = 7000
[DSM]
type = tcp
local_ip = 192.168.1.40 #群晖 NAS 在局域网中的内网 IP
local_port = 5000
remote_port = 7001
[RDP]
type = tcp
local_ip = 192.168.1.30 #电脑在局域网中的内网 IP (如是本机,也可使用 127.0.0.1)
local_port = 3389
remote_port = 7002
```
这样就在本地上新增了“DSM”和“RDP”两个可供公网访问的服务了 (它们名称可以自己取),这里分别对应内网的群晖 NAS 的后台管理界面和 PC 远程桌面。如果你需要添加更多的设备和服务供外网访问,那么只需照样画葫芦,指定正确的 IP 地址和端口号即可。
>#### 注意放行端口
每个服务的 remote_port 是远程访问时要用到的端口号,注意这些端口号也要在服务器的防火土啬和安全组里放行才能顺利访问的,如上面的 7001、7002。
>#### 启动 FRP 客户端:
假设你已将 Frp 的客户端解压缩到 ``` c:\frp ``` 目录中,那么启动 Frp 客户端的命令就是:
``` shell
c:\frp\frpc.exe -c c:\frp\frpc.ini
```
Linux 启动 Frp 客户端命令:
``` shell
./frpc -c ./frpc.ini
```
启动之后看到 “start proxy success”字样就表示启动成功了。
>### 3、进行远程访问
前面搞了这么多,我们终于可以正式使用 Frp 内网穿透来进行远程访问内网里的设备了!按照上面的配置,我们想要访问群晖 NAS 的界面,只需打开浏览器,在地址栏输入 ```服务器公网IP:7001``` 即可访问到群晖后台管理界面。
而如果需要远程桌面连接到家里的 Windows 电脑,那么打开“微软远程桌面客户端”后,在地址栏里填入 ``` 服务器公网IP:7002 ``` 即可连接。
由此,借助 Frp你就能轻松地为本地局域网内网的设备提供公网直接访问的能力了你可以用 Frp 来转发包括但不限于 ssh、http、https、转发 Unix 域套接字等服务。
上面只是最基础的教程Frp 还有很多很多高级功能,比如给 Web 增加密码保护、点对点内网穿透、设置端口白名单等等Frp 官网上也提供了很详细的文档,感兴趣的朋友可以去研究一下。
>### 写在后面:
最后,有了 Frp我们就能轻松解决没有公网 IP 的老难题了!无论家里的 NAS 、电脑还是其他网络设备,都能轻松在外访问,这可以说是无公网 IP 用户必备的工具了。
希望这篇简单 Frp 入门教程能对有远程访问需求的同学有所帮助吧。毕竟 Frp 带来的便利性是非常大的,特别是需要出差移动办公的用户,值得大家去研究和折腾一番。与 Frp 同类的软件还有 Ngrok、n2n、lanproxy 等,它们工作方式都大同小异,都需要一台服务器作为中转。

@ -0,0 +1,59 @@
---
icon: edit
date: 2021-09-15
category:
- 系统配置
tag:
- hosts
headerDepth: 5
---
# Github Hosts
# 时间2021-09-17
Github Hosts 修改,速度可能会好点
访问缓慢原因
方法小结:
ping 下找到本机电脑访问速度比较快IP,
http://ping.chinaz.com/github.com
综合其他的网友的IP
Windows hosts 路径 :
C:\\Windows\\System32\\drivers\\etc
``` hosts
# Host Start
185.199.108.154 github.githubassets.com
140.82.113.22 central.github.com
185.199.108.133 desktop.githubusercontent.com
185.199.108.153 assets-cdn.github.com
185.199.108.133 camo.githubusercontent.com
185.199.108.133 github.map.fastly.net
199.232.69.194 github.global.ssl.fastly.net
140.82.113.4 gist.github.com
185.199.108.153 github.io
140.82.112.3 github.com
140.82.113.6 api.github.com
185.199.108.133 raw.githubusercontent.com
185.199.108.133 user-images.githubusercontent.com
185.199.108.133 favicons.githubusercontent.com
185.199.108.133 avatars5.githubusercontent.com
185.199.108.133 avatars4.githubusercontent.com
185.199.108.133 avatars3.githubusercontent.com
185.199.108.133 avatars2.githubusercontent.com
185.199.108.133 avatars1.githubusercontent.com
185.199.108.133 avatars0.githubusercontent.com
185.199.108.133 avatars.githubusercontent.com
140.82.113.10 codeload.github.com
52.216.20.99 github-cloud.s3.amazonaws.com
52.217.140.249 github-com.s3.amazonaws.com
52.217.1.132 github-production-release-asset-2e65be.s3.amazonaws.com
52.217.68.28 github-production-user-asset-6210df.s3.amazonaws.com
52.217.173.153 github-production-repository-file-5c1aeb.s3.amazonaws.com
185.199.108.153 githubstatus.com
64.71.144.202 github.community
185.199.108.133 media.githubusercontent.com
# Host End
```

@ -0,0 +1,26 @@
---
icon: edit
date: 2021-09-15
category:
- 默认分类
headerDepth: 5
---
# Hello Halo
## Hello Halo
如果你看到了这一篇文章,那么证明你已经安装成功了,感谢使用 [Halo](https://halo.run) 进行创作,希望能够使用愉快。
## 相关链接
- 官网:[https://halo.run](https://halo.run)
- 文档:[https://docs.halo.run](https://docs.halo.run)
- 社区:[https://bbs.halo.run](https://bbs.halo.run)
- 主题仓库:[https://halo.run/themes.html](https://halo.run/themes.html)
- 开源地址:[https://github.com/halo-dev/halo](https://github.com/halo-dev/halo)
在使用过程中,有任何问题都可以通过以上链接找寻答案,或者联系我们。
> 这是一篇自动生成的文章,请删除这篇文章之后开始你的创作吧!

@ -0,0 +1,105 @@
---
icon: edit
date: 2022-10-13
category:
- Java
headerDepth: 5
---
# Java 实现控制台打印彩色字体和彩色背景
请记住在Java Programming 中,输出屏幕的背景颜色和文本颜色默认为黑色或白色。如果我们想在输出屏幕上突出显示某些文本,那么我们可以使用 ANSI 颜色代码并突出显示特定文本。可以参考 ANSI 转义码以了解更多信息。
句法:
```
System.out.println(ANSI_COLORNAME + "This text is colored" + ANSI_RESET);
```
从上面的语法可以看出包含此语法包含 3 个部分:
我们必须写出我们给出特定 ANSI 代码的名称。例如 public static final String ANSI_BLACK = “\u001B[30m”;
```The above is pseudo-code is to print text in black color. So here we can use ANSI_BLACK in place of ANSI_COLORNAME to print the text in Black color.```
```编程需要懂一点英语```
- 第二部分是编写我们要以该颜色打印的文本。
- 代码关闭到目前为止设置的所有 ANSI 属性,这应该将控制台返回到其默认值。
以下是ANSI颜色代码表
![image.png](/upload/2022/10/image-759ba5d2bd104e51b674c1f9c36ba66a.png)
```\u00lB unincode码 可以用 转义字符 \33 表示```
```
package com.gongyi.common.core.utils;
import org.springframework.util.ObjectUtils;
public enum PrintUtil {
RED {
public Integer getColor() {
return 31;
}
},
GREEN {
public Integer getColor() {
return 32;
}
},
YELLOW {
public Integer getColor() {
return 33;
}
},
BLUE {
public Integer getColor() {
return 34;
}
},
PURPULE {
public Integer getColor() {
return 35;
}
},
CYAN {
public Integer getColor() {
return 36;
}
},
WHITE {
public Integer getColor() {
return 37;
}
},
BLACK {
public Integer getColor() {
return 30;
}
};
public Integer getColor() {
throw new AbstractMethodError();
}
public void Println(Object val) {
val = ObjectUtils.isEmpty(val) ? "null" : val;
printSingleColor(getColor(), 2, val.toString());
}
public void Println(Object val, PrintUtil background) {
val = ObjectUtils.isEmpty(val) ? "null" : val;
printSingleColor(getColor(), background.getColor()+10,2, val.toString());
}
/**
* @param code 颜色代号:背景颜色代号(41-46);前景色代号(31-36)
* @param n 数字+m1加粗3斜体4下划线
* @param content 要打印的内容
* 格式System.out.println("\33[前景色代号;背景色代号;数字m")
* %s是字符串占位符%d 是数字占位符
*/
private void printSingleColor(int code, int n, String content) {
System.out.format("\33[%d;%dm%s\n", code, n, content + "\33[0;39m");
}
private void printSingleColor(int code, int backCode, int n, String content) {
System.out.format("\33[%d;%d;%dm%s\n", code, backCode, n, content + "\33[0;39m");
}
}
```

@ -0,0 +1,166 @@
---
icon: edit
date: 2021-09-20
category:
- Linux
tag:
- linux
- chmod
headerDepth: 5
---
# Linux chmod命令
Linux chmod英文全拼change mode命令是控制用户对文件的权限的命令
Linux/Unix 的文件调用权限分为三级 : 文件所有者Owner、用户组Group、其它用户Other Users
![](https://www.runoob.com/wp-content/uploads/2014/08/file-permissions-rwx.jpg)
只有文件所有者和超级用户可以修改文件或目录的权限。可以使用绝对模式(八进制数字模式),符号模式指定文件的权限。
![](https://www.runoob.com/wp-content/uploads/2014/08/rwx-standard-unix-permission-bits.png)
**使用权限 : 所有使用者**
**语法**
```shell
chmod [-cfvR] [--help] [--version] mode file...
```
**参数说明**
mode : 权限设定字串,格式如下 :
```shell
[ugoa...][[+-=][rwxX]...][,...]
```
其中:
- ```u``` 表示该文件的拥有者g 表示与该文件的拥有者属于同一个群体(group)者,
- ```o``` 表示其他以外的人a 表示这三者皆是。
- ```+``` 表示增加权限、- 表示取消权限、= 表示唯一设定权限。
- ```r``` 表示可读取w 表示可写入x 表示可执行X 表示只有当该文件是个子目录或者该文件已经被设定过为可执行。
其他参数说明:
- ```-c``` : 若该文件权限确实已经更改,才显示其更改动作
- ```-f``` : 若该文件权限无法被更改也不要显示错误讯息
- ```-v``` : 显示权限变更的详细资料
- ```-R``` : 对目前目录下的所有文件与子目录进行相同的权限变更(即以递归的方式逐个变更)
- ```--help``` : 显示辅助说明
- ```--version``` : 显示版本
符号模式
使用符号模式可以设置多个项目who用户类型operator操作符和 permission权限每个项目的设置可以用逗号隔开。 命令 chmod 将修改 who 指定的用户类型对文件的访问权限,用户类型由一个或者多个字母在 who 的位置来说明,如 who 的符号模式表所示:
|who| 用户类型| 说明|
|-------|------- |------- |
|u|user |文件所有者|
|g|group|文件所有者所在组|
|o|others|所有其他用户|
|a|all |所用用户, 相当于 ugo|
operator 的符号模式表:
|Operator | 说明|
|-------|------- |
|+ |为指定的用户类型增加权限 |
|- |去除指定用户类型的权限 |
|= |设置指定用户权限的设置,即将用户类型的所有权限重新设置 |
permission 的符号模式表:
模式 名字 说明
r 读 设置为可读权限
w 写 设置为可写权限
x 执行权限 设置为可执行权限
X 特殊执行权限 只有当文件为目录文件,或者其他类型的用户有可执行权限时,才将文件权限设置可执行
s setuid/gid 当文件被执行时根据who参数指定的用户类型设置文件的setuid或者setgid权限
t 粘贴位 设置粘贴位只有超级用户可以设置该位只有文件所有者u可以使用该位
八进制语法
chmod命令可以使用八进制数来指定权限。文件或目录的权限位是由9个权限位来控制每三位为一组它们分别是文件所有者User的读、写、执行用户组Group的读、写、执行以及其它用户Other的读、写、执行。历史上文件权限被放在一个比特掩码中掩码中指定的比特位设为1用来说明一个类具有相应的优先级。
|# |权限 |rwx |二进制|
|-------|------- |-------|------- |
|7 |读 + 写 + 执行 |rwx| 111|
|6 |读 + 写 |rw-| 110|
|5 |读 + 执行 |r-x| 101|
|4 |只读 |r--| 100|
|3 |写 + 执行 |-wx| 011|
|2 |只写 |-w-| 010|
|1 |只执行 |--x| 001|
|0 |无 |---| 000|
例如, 765 将这样解释:
所有者的权限用数字表达:属主的那三个权限位的数字加起来的总和。如 rwx ,也就是 4+2+1 ,应该是 7。
用户组的权限用数字表达:属组的那个权限位数字的相加的总和。如 rw- ,也就是 4+2+0 ,应该是 6。
其它用户的权限数字表达:其它用户权限位的数字相加的总和。如 r-x ,也就是 4+0+1 ,应该是 5。
实例
将文件 file1.txt 设为所有人皆可读取 :
```shell
chmod ugo+r file1.txt
```
将文件 file1.txt 设为所有人皆可读取 :
```shell
chmod a+r file1.txt
```
将文件 file1.txt 与 file2.txt 设为该文件拥有者,与其所属同一个群体者可写入,但其他以外的人则不可写入 :
```shell
chmod ug+w,o-w file1.txt file2.txt
```
为 ex1.py 文件拥有者增加可执行权限:
```shell
chmod u+x ex1.py
```
将目前目录下的所有文件与子目录皆设为任何人可读取 :
```shell
chmod -R a+r *
```
此外chmod也可以用数字来表示权限如 :
```shell
chmod 777 file
```
语法为:
```shell
chmod abc file
```
其中a,b,c各为一个数字分别表示User、Group、及Other的权限。
**r=4w=2x=1**
若要 rwx 属性则 4+2+1=7
若要 rw- 属性则 4+2=6
若要 r-x 属性则 4+1=5。
```shell
chmod a=rwx file
```
```shell
chmod 777 file
```
效果相同
```shell
chmod ug=rwx,o=x file
```
```shell
chmod 771 file
```
效果相同
若用 ```chmod 4755 filename``` 可使此程序具有 root 的权限。
**更多说明**
|命令| 说明|
|-------|-------|
|chmod a+r file |给file的所有用户增加读权限|
|chmod a-x file |删除file的所有用户的执行权限|
|chmod a+rw file| 给file的所有用户增加读写权限|
|chmod +rwx file| 给file的所有用户增加读写执行权限|
|chmod u=rw,go= file| 对file的所有者设置读写权限清空该用户组和其他用户对file的所有权限空格代表无权限|
|chmod -R u+r,go-r docs| 对目录docs和其子目录层次结构中的所有文件给用户增加读权限而对用户组和其他用户删除读权限|
|chmod 664 file |对file的所有者和用户组设置读写权限, 为其其他用户设置读权限|
|chmod 0755 file| 相当于u=rwx (4+2+1),go=rx (4+1 & 4+1)。0 没有特殊模式。|
|chmod 4755 file| 4设置了设置用户ID位剩下的相当于 u=rwx (4+2+1),go=rx (4+1 & 4+1)。|
|find path/ -type d -exec chmod a-x {} \;| 删除可执行权限对path/以及其所有的目录(不包括文件)的所有用户,使用'-type f'匹配文件|
|find path/ -type d -exec chmod a+x {} \;| 允许所有用户浏览或通过目录path/|

@ -0,0 +1,74 @@
---
icon: edit
date: 2021-10-16
category:
- Docker
- Linux
tag:
- Docker
- linux
headerDepth: 5
---
# Linux 安装 Docker
# centos下安装docker
> 其他系统参照如下文档
https://docs.docker.com/engine/install/centos/
## 1、移除以前docker相关包
``` shell
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
```
## 2、配置yum源
``` shell
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
```
## 3、安装docker
``` shell
sudo yum install -y docker-ce docker-ce-cli containerd.io
#以下是在安装k8s的时候使用
yum install -y docker-ce-20.10.7 docker-ce-cli-20.10.7 containerd.io-1.4.6
```
## 4、启动
```
systemctl enable docker --now #--now 立即执行
```
## 5、配置加速
这里额外添加了docker的生产环境核心配置cgroup
``` json
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://82m9ar63.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
```

@ -0,0 +1,233 @@
---
icon: edit
date: 2021-10-17
category:
- Docker
- Linux
tag:
- docker-compose
- Docker
headerDepth: 5
---
# Linux 安装 docker-compose
# docker-compose
> docker compose 在 Docker 容器运用中具有很大的学习意义docker compose 是一个整合发布应用的利器。而使用 docker compose 时,懂得如何编排 docker compose 配置文件是很重要的。
## 安装
>Linux 上我们可以从 Github 上下载它的二进制包来使用最新发行的版本地址https://github.com/docker/compose/releases。
### 方式一:
```shell
#curl -L "https://github.com/docker/compose/releases/download/v2.17.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
#github太卡了网好和科学上网的同学可以使用
curl -L "https://ghproxy.com/https://github.com/docker/compose/releases/download/v2.17.2/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
#curl -L https://get.daocloud.io/docker/compose/releases/download/1.12.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose version # 查看版本号,测试是否安装成功
你可以通过修改URL中的版本可以自定义您的需要的版本。
```
### 方式二:
```shell
  1、安装python-pip
  yum -y install epel-release
  yum -y install python-pip
  2、安装docker-compose
  pip install docker-compose
  待安装完成后,执行查询版本的命令确认安装成功
  docker-compose version
  spring.dubbo
  application.name
  registry.port
```
## 参数详解
[docker 编排参数详解docker-compose.yml 配置文件编写)](https://xie.infoq.cn/article/d666cde8f2131ff25ddf19ad8)
## 常用命令
### 1、Docker-Compose命令格式
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
命令选项如下:
-ffile FILE指定Compose模板文件默认为docker-compose.yml可以多次指定。
-pproject-name NAME指定项目名称默认将使用所在目录名称作为项目名。
-x-network-driver 使用Docker的可拔插网络后端特性需要Docker 1.9+版本)
-x-network-driver DRIVER指定网络后端的驱动默认为bridge需要Docker 1.9+版本)
-verbose输出更多调试信息
-vversion打印版本并退出
### 2、docker-compose up
```docker-compose up [options] [--scale SERVICE=NUM...] [SERVICE...]```
选项包括:
-d 在后台运行服务容器
no-color 不使用颜色来区分不同的服务的控制输出
no-deps 不启动服务所链接的容器
force-recreate 强制重新创建容器不能与no-recreate同时使用
no-recreate 如果容器已经存在则不重新创建不能与force-recreate同时使用
no-build 不自动构建缺失的服务镜像
build 在启动容器前构建服务镜像
abort-on-container-exit 停止所有容器,如果任何一个容器被停止,不能与-d同时使用
-t, timeout TIMEOUT 停止容器时候的超时默认为10秒
remove-orphans 删除服务中没有在compose文件中定义的容器
scale SERVICE=NUM 设置服务运行容器的个数将覆盖在compose中通过scale指定的参数
```docker-compose up```
启动所有服务
```docker-compose up -d```
在后台所有启动服务
-f 指定使用的Compose模板文件默认为docker-compose.yml可以多次指定。
```docker-compose -f docker-compose.yml up -d```
### 3、docker-compose ps
```docker-compose ps [options] [SERVICE...]```
```docker-compose ps```
列出项目中目前的所有容器
### 4、docker-compose stop
```docker-compose stop [options] [SERVICE...]```
选项包括:
-t, timeout TIMEOUT 停止容器时候的超时默认为10秒
```docker-compose stop```
停止正在运行的容器可以通过docker-compose start 再次启动
### 5、docker-compose -h
```docker-compose -h```
查看帮助
### 6、docker-compose down
```docker-compose down [options]```
停止和删除容器、网络、卷、镜像。
选项包括:
rmi type删除镜像类型必须是all删除compose文件中定义的所有镜像local删除镜像名为空的镜像
-v, volumes删除已经在compose文件中定义的和匿名的附在容器上的数据卷
remove-orphans删除服务中没有在compose中定义的容器
```docker-compose down```
停用移除所有容器以及网络相关
### 7、docker-compose logs
```docker-compose logs [options] [SERVICE...]```
查看服务容器的输出。默认情况下docker-compose将对不同的服务输出使用不同的颜色来区分。可以通过no-color来关闭颜色。
```docker-compose logs```
查看服务容器的输出
### 8、docker-compose build
```docker-compose build [options] [--build-arg key=val...] [SERVICE...]```
构建(重新构建)项目中的服务容器。
选项包括:
compress 通过gzip压缩构建上下环境
force-rm 删除构建过程中的临时容器
no-cache 构建镜像过程中不使用缓存
pull 始终尝试通过拉取操作来获取更新版本的镜像
-m, memory MEM为构建的容器设置内存大小
build-arg key=val为服务设置build-time变量
服务容器一旦构建后将会带上一个标记名。可以随时在项目目录下运行docker-compose build来重新构建服务
### 9、docker-compose pull
docker-compose pull [options] [SERVICE...]
拉取服务依赖的镜像。
选项包括:
ignore-pull-failures忽略拉取镜像过程中的错误
parallel多个镜像同时拉取
quiet拉取镜像过程中不打印进度信息
```docker-compose pull```
拉取服务依赖的镜像
### 10、docker-compose restart
```docker-compose restart [options] [SERVICE...]```
重启项目中的服务。
选项包括:
-t, timeout TIMEOUT指定重启前停止容器的超时默认为10秒
```docker-compose restart```
重启项目中的服务
### 11、docker-compose rm
```docker-compose rm [options] [SERVICE...]```
删除所有(停止状态的)服务容器。
选项包括:
f, force强制直接删除包括非停止状态的容器
-v删除容器所挂载的数据卷
```docker-compose rm```
删除所有停止状态的服务容器。推荐先执行docker-compose stop命令来停止容器。
### 12、docker-compose start
```docker-compose start [SERVICE...]```
```docker-compose start```
启动已经存在的服务容器。
### 13、docker-compose run
```docker-compose run [options] [-v VOLUME...] [-p PORT...] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]```
在指定服务上执行一个命令。
```docker-compose run ubuntu ping www.baidu.com```
在指定容器上执行一个ping命令。
### 14、docker-compose scale
```docker-compose scale web=3 db=2```
设置指定服务运行的容器个数。通过service=num的参数来设置数量
### 15、docker-compose pause
```docker-compose pause [SERVICE...]```
暂停一个服务容器
### 16、docker-compose kill
```docker-compose kill [options] [SERVICE...]```
通过发送SIGKILL信号来强制停止服务容器。
支持通过-s参数来指定发送的信号例如通过如下指令发送SIGINT信号
```docker-compose kill -s SIGINT```
### 17、dokcer-compose config
```docker-compose config [options]```
验证并查看compose文件配置。
选项包括:
resolve-image-digests 将镜像标签标记为摘要
-q, quiet 只验证配置,不输出。 当配置正确时,不输出任何内容,当文件配置错误,输出错误信息
services 打印服务名,一行一个
volumes 打印数据卷名,一行一个
### 18、docker-compose create
```docker-compose create [options] [SERVICE...]```
为服务创建容器。
选项包括:
force-recreate重新创建容器即使配置和镜像没有改变不兼容no-recreate参数
no-recreate如果容器已经存在不需要重新创建不兼容force-recreate参数
no-build不创建镜像即使缺失
build创建容器前生成镜像
### 19、docker-compose exec
```docker-compose exec [options] SERVICE COMMAND [ARGS...]```
选项包括:
-d 分离模式,后台运行命令。
privileged 获取特权。
user USER 指定运行的用户。
-T 禁用分配TTY默认docker-compose exec分配TTY。
index=index当一个服务拥有多个容器时可通过该参数登陆到该服务下的任何服务例如docker-compose exec index=1 web /bin/bash web服务中包含多个容器
### 20、docker-compose port
```docker-compose port [options] SERVICE PRIVATE_PORT```
显示某个容器端口所映射的公共端口。
选项包括:
protocol=proto指定端口协议TCP默认值或者UDP
index=index如果同意服务存在多个容器指定命令对象容器的序号默认为1
### 21、docker-compose push
```docker-compose push [options] [SERVICE...]```
推送服务依的镜像。
选项包括:
ignore-push-failures 忽略推送镜像过程中的错误
### 22、docker-compose stop
```docker-compose stop [options] [SERVICE...]```
显示各个容器运行的进程情况。
### 23、docker-compose unpause
```docker-compose unpause [SERVICE...]```
恢复处于暂停状态中的服务。
### 24、docker-compose version
```docker-compose version```
打印版本信息。

@ -0,0 +1,556 @@
---
icon: edit
date: 2021-10-16
category:
- Docker
- Linux
- Kubernetes
tag:
- Docker
- linux
- Kubernetes
headerDepth: 5
---
# Linux 安装Kubernetes
# kubeadm创建集群
> 请参照以前Docker安装。先提前为所有机器安装Docker
1、安装kubeadm
- 一台兼容的 Linux 主机。Kubernetes 项目为基于 Debian 和 Red Hat 的 Linux 发行版以及一些不提供包管理器的发行版提供通用的指令
- 每台机器 2 GB 或更多的 RAM (如果少于这个数字将会影响你应用的运行内存)
- 2 CPU 核或更多
- 集群中的所有机器的网络彼此均能相互连接(公网和内网都可以)
- 设置防火墙放行规则
- 节点之中不可以有重复的主机名、MAC 地址或 product_uuid。请参见这里了解更多详细信息。
- 设置不同hostname
- 开启机器上的某些端口。请参见这里 了解更多详细信息。
- 内网互信
- 禁用交换分区。为了保证 kubelet 正常工作,你 必须 禁用交换分区。
- 永久关闭
### 1、基础环境
> 所有机器执行以下操作
``` bash
#各个机器设置自己的域名
hostnamectl set-hostname xxxx
# 将 SELinux 设置为 permissive 模式(相当于将其禁用)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
#关闭swap
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
#允许 iptables 检查桥接流量
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sudo sysctl --system
```
### 2、安装kubelet、kubeadm、kubectl
```bash
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF
sudo yum install -y kubelet-1.20.9 kubeadm-1.20.9 kubectl-1.20.9 --disableexcludes=kubernetes
sudo systemctl enable --now kubelet
```
> kubelet 现在每隔几秒就会重启,因为它陷入了一个等待 kubeadm 指令的死循环
## 2、使用kubeadm引导集群
### 1、下载各个机器需要的镜像
```bash
sudo tee ./images.sh <<-'EOF'
#!/bin/bash
images=(
kube-apiserver:v1.20.9
kube-proxy:v1.20.9
kube-controller-manager:v1.20.9
kube-scheduler:v1.20.9
coredns:1.7.0
etcd:3.4.13-0
pause:3.2
)
for imageName in ${images[@]} ; do
docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/$imageName
done
EOF
chmod +x ./images.sh && ./images.sh
```
### 2、初始化主节点
```bash
#所有机器添加master域名映射以下需要修改为自己的
echo "172.31.0.4 cluster-endpoint" >> /etc/hosts
#主节点初始化
kubeadm init \
--apiserver-advertise-address=172.31.0.4 \
--control-plane-endpoint=cluster-endpoint \
--image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
--kubernetes-version v1.20.9 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=192.168.0.0/16
#所有网络范围不重叠
```
```bash
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join cluster-endpoint:6443 --token hums8f.vyx71prsg74ofce7 \
--discovery-token-ca-cert-hash sha256:a394d059dd51d68bb007a532a037d0a477131480ae95f75840c461e85e2c6ae3 \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join cluster-endpoint:6443 --token hums8f.vyx71prsg74ofce7 \
--discovery-token-ca-cert-hash sha256:a394d059dd51d68bb007a532a037d0a477131480ae95f75840c461e85e2c6ae3
```
```bash
#查看集群所有节点
kubectl get nodes
#根据配置文件,给集群创建资源
kubectl apply -f xxxx.yaml
#查看集群部署了哪些应用?
docker ps === kubectl get pods -A
# 运行中的应用在docker里面叫容器在k8s里面叫Pod
kubectl get pods -A
```
### 3、根据提示继续
> master成功后提示如下
> ![image.png](/upload/2021/10/image-d246070956b74a95bef1c2b9fd9f19dd.png)
#### 1、设置.kube/config
复制上面命令
#### 2、安装网络组件
[calico官网](https://docs.projectcalico.org/getting-started/kubernetes/self-managed-onprem/onpremises#install-calico-with-kubernetes-api-datastore-more-than-50-nodes)
```bash
curl https://docs.projectcalico.org/manifests/calico.yaml -O
kubectl apply -f calico.yaml
```
### 4、加入node节点
```bash
kubeadm join cluster-endpoint:6443 --token x5g4uy.wpjjdbgra92s25pp \
--discovery-token-ca-cert-hash sha256:6255797916eaee52bf9dda9429db616fcd828436708345a308f4b917d3457a22
```
>新令牌
kubeadm token create --print-join-command
>高可用部署方式,也是在这一步的时候,使用添加主节点的命令即可
### 5、验证集群
- 验证集群节点状态
- kubectl get nodes
### 6、部署dashboard
#### 1、部署
>kubernetes官方提供的可视化界面
https://github.com/kubernetes/dashboard
```bash
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml
```
```bash
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: v1
kind: Namespace
metadata:
name: kubernetes-dashboard
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
ports:
- port: 443
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-certs
namespace: kubernetes-dashboard
type: Opaque
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-csrf
namespace: kubernetes-dashboard
type: Opaque
data:
csrf: ""
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-key-holder
namespace: kubernetes-dashboard
type: Opaque
---
kind: ConfigMap
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-settings
namespace: kubernetes-dashboard
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
rules:
# Allow Dashboard to get, update and delete Dashboard exclusive secrets.
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
verbs: ["get", "update", "delete"]
# Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["kubernetes-dashboard-settings"]
verbs: ["get", "update"]
# Allow Dashboard to get metrics.
- apiGroups: [""]
resources: ["services"]
resourceNames: ["heapster", "dashboard-metrics-scraper"]
verbs: ["proxy"]
- apiGroups: [""]
resources: ["services/proxy"]
resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
verbs: ["get"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
rules:
# Allow Metrics Scraper to get metrics from the Metrics server
- apiGroups: ["metrics.k8s.io"]
resources: ["pods", "nodes"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kubernetes-dashboard
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kubernetes-dashboard
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: kubernetes-dashboard
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
spec:
containers:
- name: kubernetes-dashboard
image: kubernetesui/dashboard:v2.3.1
imagePullPolicy: Always
ports:
- containerPort: 8443
protocol: TCP
args:
- --auto-generate-certificates
- --namespace=kubernetes-dashboard
# Uncomment the following line to manually specify Kubernetes API server Host
# If not specified, Dashboard will attempt to auto discover the API server and connect
# to it. Uncomment only if the default does not work.
# - --apiserver-host=http://my-address:port
volumeMounts:
- name: kubernetes-dashboard-certs
mountPath: /certs
# Create on-disk volume to store exec logs
- mountPath: /tmp
name: tmp-volume
livenessProbe:
httpGet:
scheme: HTTPS
path: /
port: 8443
initialDelaySeconds: 30
timeoutSeconds: 30
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1001
runAsGroup: 2001
volumes:
- name: kubernetes-dashboard-certs
secret:
secretName: kubernetes-dashboard-certs
- name: tmp-volume
emptyDir: {}
serviceAccountName: kubernetes-dashboard
nodeSelector:
"kubernetes.io/os": linux
# Comment the following tolerations if Dashboard must not be deployed on master
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: dashboard-metrics-scraper
name: dashboard-metrics-scraper
namespace: kubernetes-dashboard
spec:
ports:
- port: 8000
targetPort: 8000
selector:
k8s-app: dashboard-metrics-scraper
---
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: dashboard-metrics-scraper
name: dashboard-metrics-scraper
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: dashboard-metrics-scraper
template:
metadata:
labels:
k8s-app: dashboard-metrics-scraper
annotations:
seccomp.security.alpha.kubernetes.io/pod: 'runtime/default'
spec:
containers:
- name: dashboard-metrics-scraper
image: kubernetesui/metrics-scraper:v1.0.6
ports:
- containerPort: 8000
protocol: TCP
livenessProbe:
httpGet:
scheme: HTTP
path: /
port: 8000
initialDelaySeconds: 30
timeoutSeconds: 30
volumeMounts:
- mountPath: /tmp
name: tmp-volume
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1001
runAsGroup: 2001
serviceAccountName: kubernetes-dashboard
nodeSelector:
"kubernetes.io/os": linux
# Comment the following tolerations if Dashboard must not be deployed on master
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
volumes:
- name: tmp-volume
emptyDir: {}
```
#### 2、设置访问端口
```bash
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
```
>type: ClusterIP 改为 type: NodePort
```bash
kubectl get svc -A |grep kubernetes-dashboard
## 找到端口,在安全组放行
```
访问: https://集群任意IP:端口 https://139.198.165.238:32759
#### 3、创建访问账号
```bash
#创建访问账号准备一个yaml文件 vi dash.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
```
```bash
kubectl apply -f dash.yaml
```
#### 4、令牌访问
```bash
#获取访问令牌
kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"
```
```bash
eyJhbGciOiJSUzI1NiIsImtpZCI6InpXSkU0TjhCUmVKQzBJaC03Nk9ES2NMZ1daRTRmQ1FMZU9rRUJ3VXRnM3MifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLXgyczhmIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIzOTZmYjdlNS0wMjA2LTQxMjctOGQzYS0xMzRlODVmYjU0MDAiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.Hf5mhl35_R0iBfBW7fF198h_klEnN6pRKfk_roAzOtAN-Aq21E4804PUhe9Rr9e_uFzLfoFDXacjJrHCuhiML8lpHIfJLK_vSD2pZNaYc2NWZq2Mso-BMGpObxGA23hW0nLQ5gCxlnxIAcyE76aYTAB6U8PxpvtVdgUknBVrwXG8UC_D8kHm9PTwa9jgbZfSYAfhOHWmZxNYo7CF2sHH-AT_WmIE8xLmB7J11vDzaunv92xoUoI0ju7OBA2WRr61bOmSd8WJgLCDcyBblxz4Wa-3zghfKlp0Rgb8l56AAI7ML_snF59X6JqaCuAcCJjIu0FUTS5DuyIObEeXY-z-Rw
```
5、界面
![image.png](/upload/2021/10/image-0f8e1e2e40a24a7baf1b6535b9f70374.png)

@ -0,0 +1,113 @@
---
icon: edit
date: 2022-12-15
category:
- 系统配置
- Linux
tag:
- mysql
headerDepth: 5
---
# MySQL每天定时备份
备份是容灾的基础,是指为防止系统出现操作失误或系统故障导致数据丢失,而将全部或部分数据集合从应用主机的硬盘或阵列复制到其它的存储介质的过程。而对于一些网站、系统来说,数据库就是一切,所以做好数据库的备份是至关重要的!
这里主要以本地磁盘为存储介质讲一下计划任务的添加使用,基本的备份脚本,其它存储介质只是介质的访问方式可能不大一样。
#### 1、查看磁盘空间情况
既然是定时备份,就要选择一个空间充足的磁盘空间,避免出现因空间不足导致备份失败,数据丢失的恶果!
存储到当前磁盘这是最简单,却是最不推荐的;服务器有多块硬盘,最好是把备份存放到另一块硬盘上;有条件就选择更好更安全的存储介质;
```shell
df -h
```
2、创建备份目录
上面我们使用命令看出/home下空间比较充足所以可以考虑在/home保存备份文件
```shell
cd /home
mkdir backupcd backup
```
#### 3、创建备份Shell脚本:
注意把以下命令中的DatabaseName换为实际的数据库名称
当然,你也可以使用其实的命名规则!
```shell
vi bkDatabaseName.sh
```
输入/粘贴以下内容:
```shell
#!/bin/bash
mysqldump -uusername -ppassword DatabaseName > /home/backup/DatabaseName_$(date +%Y%m%d_%H%M%S).sql
```
对备份进行压缩:
```shell
#!/bin/bash
mysqldump -uusername -ppassword DatabaseName | gzip > /home/backup/DatabaseName_$(date +%Y%m%d_%H%M%S).sql.gz
```
注意:
把 username 替换为实际的用户名;
把 password 替换为实际的密码;
把 DatabaseName 替换为实际的数据库名;
#### 4、添加可执行权限
```shell
chmod u+x bkDatabaseName.sh
```
添加可执行权限之后先执行一下,看看脚本有没有错误,能不能正常使用;
```shell
./bkDatabaseName.sh
```
#### 5、添加计划任务
检测或安装 crontab
确认crontab是否安装
执行 crontab 命令如果报 command not found就表明没有安装
如时没有安装 crontab需要先安装它具体步骤请参考
CentOS下使用yum命令安装计划任务程序crontab
使用rpm命令从CentOS系统盘安装计划任务程序crontab
添加计划任务
执行命令:
```shell
crontab -e
```
这时就像使用vi编辑器一样可以对计划任务进行编辑。
输入以下内容并保存:
```shell
*/1 * * * * /home/backup/bkDatabaseName.sh
```
具体是什么意思呢?
意思是每一分钟执行一次shell脚本“/home/backup/bkDatabaseName.sh”。
#### 6、测试任务是否执行
很简单我们就执行几次“ls”命令看看一分钟过后文件有没有被创建就可以了
如果任务执行失败了,可以通过以下命令查看任务日志:
```shell
tail -f /var/log/cron
```
输出类似如下:
``` shell
Dec 15 10:00:01 loaclhost CROND[51208]: (root) CMD (/usr/lib64/sa/sa1 1 1)
Dec 15 10:01:01 loaclhost CROND[51441]: (root) CMD (run-parts /etc/cron.hourly)
Dec 15 10:01:01 loaclhost run-parts(/etc/cron.hourly)[51441]: starting 0anacron
Dec 15 10:01:01 loaclhost run-parts(/etc/cron.hourly)[51453]: finished 0anacron
Dec 15 10:01:01 loaclhost run-parts(/etc/cron.hourly)[51441]: starting mcelog.cron
Dec 15 10:01:01 loaclhost run-parts(/etc/cron.hourly)[51460]: finished mcelog.cron
Dec 15 10:10:01 loaclhost CROND[53628]: (root) CMD (/usr/lib64/sa/sa1 1 1)
Dec 15 10:16:58 loaclhost crontab[55380]: (root) BEGIN EDIT (root)
Dec 15 10:18:30 loaclhost crontab[55380]: (root) REPLACE (root)
Dec 15 10:18:30 loaclhost crontab[55380]: (root) END EDIT (root)
Dec 15 10:19:01 loaclhost crond[5673]: (root) RELOAD (/var/spool/cron/root)
Dec 15 10:19:01 loaclhost CROND[55906]: (root) CMD (/bak/bak_sql.sh)
Dec 15 10:19:01 loaclhost CROND[55905]: (root) MAIL (mailed 54 bytes of output but got status 0x007f#012)
Dec 15 10:20:01 loaclhost CROND[56148]: (root) CMD (/bak/bak_sql.sh)
Dec 15 10:20:01 loaclhost CROND[56149]: (root) CMD (/usr/lib64/sa/sa1 1 1)
Dec 15 10:20:01 loaclhost CROND[56146]: (root) MAIL (mailed 54 bytes of output but got status 0x007f#012)
```

@ -0,0 +1,41 @@
---
icon: edit
date: 2022-10-13
category:
- mysql
tag:
- mysql
headerDepth: 5
---
# Mysql too many connections 解决方法
最近写javaee项目的时候mysql报了too many connections的错误百度的内容有一些有问题所以我重新写一下我的解决方法。
1. mysql -u root -p 回车输入密码进入mysql
![image.png](/upload/2022/10/image-6007218e54be45fd990f719385c892fd.png)
2. show processlist;
查看连接数可以发现有很多连接处于sleep状态这些其实是暂时没有用的所以可以kill掉
3. show variables like "max_connections";
查看最大连接数应该是与上面查询到的连接数相同才会出现too many connections的情况
4. set GLOBAL max_connections=1000;
修改最大连接数但是这不是一劳永逸的方法应该要让它自动杀死那些sleep的进程。
show global variables like 'wait_timeout';
5. 这个数值指的是mysql在关闭一个非交互的连接之前要等待的秒数默认是28800s
set global wait_timeout=300;
6. 修改这个数值,这里可以随意,最好控制在几分钟内
![image.png](/upload/2022/10/image-08ad270052c547b09de075eb23063f2f.png)
7. set global interactive_timeout=500;
修改这个数值表示mysql在关闭一个连接之前要等待的秒数至此可以让mysql自动关闭那些没用的连接但要注意的是正在使用的连接到了时间也会被关闭因此这个时间值要合适
8. 批量kill之前没用的sleep连接在网上搜索的方法对我都不奏效因此只好使用最笨的办法一个一个kill
select concat('KILL ',id,';') from information_schema.processlist where user='root'; 先把要kill的连接id都查询出来
复制中间的kill id;内容到word文档
替换掉符号“|”和回车符在word中查询^p即可查询到回车符
把修改过的内容复制回终端,最后按回车执行!

@ -0,0 +1,47 @@
---
icon: edit
date: 2023-03-26
category:
- 系统配置
tag:
- nginx
headerDepth: 5
---
# Nginx反向代理域名但域名IP变化后还解析的是变化前的IP解决方法
之前博客的代理 proxy_pass 时直接指定域名是可以用的,比如
```
location / {
proxy_pass http://local.wuanwanghao.top:30550;
}
```
#### 遇到一个问题是:
如果路由器因为断电或者掉线之类的原因重新拨号后ip发生变化此处nginx就无法反向代理了必须重启一次nginx才行。
#### 解决方法:
```
server {
listen 8080;
server_name localhost;
ssl_prefer_server_ciphers on;
#配置域名解析 validDNS缓存时间也可以不指定缓存时间会默认根据域名的TTL时间 ipv6on或off指定该域名解析为ipv6地址。
resolver 202.102.134.68 114.114.114.114 valid=30 ipv6=off;
#指定解析域名时DNS服务器的超时时间也可以不指定
resolver_timeout 30s;
#设置变量在使用resolver之后必须使用set设置变量来代替域名否则会报错
set $true_url "local.wuanwanghao.top";
location / {
proxy_pass http://$true_url:30550;
}
}
```
resolver后接指定的DNS服务器多个用空格隔开。resolver可以在http里面全局设定也可以在server里面设定。
validDNS缓存时间也可以不指定缓存时间会默认根据域名的TTL时间。
ipv6on或off指定该域名解析为ipv6地址。
resolver_timeout指定解析域名时DNS服务器的超时时间也可以不指定。
set 设置变量在使用resolver之后必须使用set设置变量来代替域名否则会报错。另外set不能写到 location里面否则不会生效。注意set变量在server中可以设置成功http中语法不允许。
这样才解决动态dns解析访问问题。

@ -0,0 +1,22 @@
---
icon: edit
date: 2023-02-14
category:
- 系统配置
- 内网穿透
headerDepth: 5
---
# PPTP/L2TP内外网VPN映射端口及协议
```
PPTP需开放端口
UDP:1723
L2TP需开放端口
UDP:500
UDP:4500
UDP:1701
注意端口映射时应该将协议设置为UDP否则无法生效
```

@ -0,0 +1,544 @@
---
icon: edit
date: 2021-09-19
category:
- python
tag:
- python
headerDepth: 5
---
# Python3 基本数据类型
# Python3 基本数据类型
>Python 中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。
>在 Python 中,变量就是变量,它没有类型,我们所说的"类型"是变量所指的内存中对象的类型。
>等号(=)用来给变量赋值。
>等号(=)运算符左边是一个变量名,等号(=)运算符右边是存储在变量中的值。例如:
```python
#!/usr/bin/python3
counter = 100 # 整型变量
miles = 1000.0 # 浮点型变量
name = "runoob" # 字符串
print (counter)
print (miles)
print (name)
```
执行以上程序会输出如下结果:
```
100
1000.0
runoob
```
### 多个变量赋值
Python允许你同时为多个变量赋值。例如
``` python
a = b = c = 1
```
以上实例,创建一个整型对象,值为 1从后向前赋值三个变量被赋予相同的数值。
您也可以为多个对象指定多个变量。例如:
``` python
a, b, c = 1, 2, "runoob"
```
以上实例,两个整型对象 1 和 2 的分配给变量 a 和 b字符串对象 "runoob" 分配给变量 c。
### 标准数据类型
Python3 中有六个标准的数据类型:
- Number数字
- String字符串
- List列表
- Tuple元组
- Set集合
- Dictionary字典
Python3 的六个标准数据类型中:
- **不可变数据3 个)****Number**(数字)、**String**(字符串)、**Tuple**(元组);
- **可变数据3 个)****List**(列表)、**Dictionary**(字典)、**Set**(集合)。
## Number数字
Python3 支持 **int、float、bool、complex**(复数)。
在Python 3里只有一种整数类型 int表示为长整型没有 python2 中的 Long。
像大多数语言一样,数值类型的赋值和计算都是很直观的。
内置的 type() 函数可以用来查询变量所指的对象类型。
``` python
>>> a, b, c, d = 20, 5.5, True, 4+3j
>>> print(type(a), type(b), type(c), type(d))
<class 'int'> <class 'float'> <class 'bool'> <class 'complex'>
```
此外还可以用 isinstance 来判断:
```python
>>> a = 111
>>> isinstance(a, int)
True
>>>
```
isinstance 和 type 的区别在于:
type()不会认为子类是一种父类类型。
isinstance()会认为子类是一种父类类型。
```python
>>> class A:
... pass
...
>>> class B(A):
... pass
...
>>> isinstance(A(), A)
True
>>> type(A()) == A
True
>>> isinstance(B(), A)
True
>>> type(B()) == A
False
```
>**注意:**Python3 中bool 是 int 的子类True 和 False 可以和数字相加, True==1、False==0 会返回 True但可以通过 is 来判断类型。
```python
>>> issubclass(bool, int)
True
>>> True==1
True
>>> False==0
True
>>> True+1
2
>>> False+1
1
>>> 1 is True
False
>>> 0 is False
False
```
在 Python2 中是没有布尔型的,它用数字 0 表示 False用 1 表示 True。
当你指定一个值时Number 对象就会被创建:
```python
var1 = 1
var2 = 10
```
您也可以使用del语句删除一些对象引用。
del语句的语法是
```python
del var1[,var2[,var3[....,varN]]]
```
您可以通过使用del语句删除单个或多个对象。例如
```python
del var
del var_a, var_b
```
### 数值运算
```python
>>> 5 + 4 # 加法
9
>>> 4.3 - 2 # 减法
2.3
>>> 3 * 7 # 乘法
21
>>> 2 / 4 # 除法,得到一个浮点数
0.5
>>> 2 // 4 # 除法,得到一个整数
0
>>> 17 % 3 # 取余
2
>>> 2 ** 5 # 乘方
32
```
**注意**
1、Python可以同时为多个变量赋值如a, b = 1, 2。
2、一个变量可以通过赋值指向不同类型的对象。
3、数值的除法包含两个运算符/ 返回一个浮点数,// 返回一个整数。
4、在混合计算时Python会把整型转换成为浮点数。
### 数值类型实例
|int |float |complex|
|-------|-------|-------|
|10 |0.0 |3.14j|
|100 |15.20 |45.j|
|-786 |-21.9 |9.322e-36j|
|080 |32.3e+18 |.876j|
|-0490 |-90. |-.6545+0J|
|-0x260 |-32.54e100 |3e+26J|
|0x69 |70.2E-12 |4.53e-7j|
>Python还支持复数复数由实数部分和虚数部分构成可以用a + bj,或者complex(a,b)表示, 复数的实部a和虚部b都是浮点型
## String字符串
Python中的字符串用单引号 ' 或双引号 " 括起来,同时使用反斜杠 \ 转义特殊字符。
字符串的截取的语法格式如下:
```变量[头下标:尾下标]```
索引值以 0 为开始值,-1 为从末尾的开始位置。
![](https://static.runoob.com/wp-content/uploads/123456-20200923-1.svg)
加号 ```+```是字符串的连接符, 星号 ```*```表示复制当前字符串,与之结合的数字为复制的次数。实例如下:
```python
#!/usr/bin/python3
str = 'Runoob'
print (str) # 输出字符串
print (str[0:-1]) # 输出第一个到倒数第二个的所有字符
print (str[0]) # 输出字符串第一个字符
print (str[2:5]) # 输出从第三个开始到第五个的字符
print (str[2:]) # 输出从第三个开始的后的所有字符
print (str * 2) # 输出字符串两次,也可以写成 print (2 * str)
print (str + "TEST") # 连接字符串
```
执行以上程序会输出如下结果:
```console
Runoob
Runoo
R
noo
noob
RunoobRunoob
RunoobTEST
```
Python 使用反斜杠 ```\``` 转义特殊字符,如果你不想让反斜杠发生转义,可以在字符串前面添加一个 ```r```,表示原始字符串:
```python
>>> print('Ru\noob')
Ru
oob
>>> print(r'Ru\noob')
Ru\noob
>>>
```
另外,反斜杠(```\```)可以作为续行符,表示下一行是上一行的延续。也可以使用 """...""" 或者 '''...''' 跨越多行。
注意Python 没有单独的字符类型一个字符就是长度为1的字符串。
```python
>>> word = 'Python'
>>> print(word[0], word[5])
P n
>>> print(word[-1], word[-6])
n P
```
与 C 字符串不同的是Python 字符串不能被改变。向一个索引位置赋值比如word[0] = 'm'会导致错误。
**注意:**
- 1、反斜杠可以用来转义使用r可以让反斜杠不发生转义。
- 2、字符串可以用+运算符连接在一起,用*运算符重复。
- 3、Python中的字符串有两种索引方式从左往右以0开始从右往左以-1开始。
- 4、Python中的字符串不能改变。
## List列表
List列表 是 Python 中使用最频繁的数据类型。
列表可以完成大多数集合类的数据结构实现。列表中元素的类型可以不相同,它支持数字,字符串甚至可以包含列表(所谓嵌套)。
列表是写在方括号 ```[]``` 之间、用逗号分隔开的元素列表。
和字符串一样,列表同样可以被索引和截取,列表被截取后返回一个包含所需元素的新列表。
列表截取的语法格式如下:
```变量[头下标:尾下标]```
索引值以 ```0```为开始值,```-1``` 为从末尾的开始位置。
![](https://www.runoob.com/wp-content/uploads/2014/08/list_slicing1_new1.png)
加号 ```+``` 是列表连接运算符,星号 ```*``` 是重复操作。如下实例:
```python
#!/usr/bin/python3
list = [ 'abcd', 786 , 2.23, 'runoob', 70.2 ]
tinylist = [123, 'runoob']
print (list) # 输出完整列表
print (list[0]) # 输出列表第一个元素
print (list[1:3]) # 从第二个开始输出到第三个元素
print (list[2:]) # 输出从第三个元素开始的所有元素
print (tinylist * 2) # 输出两次列表
print (list + tinylist) # 连接列表
```
以上实例输出结果:
```console
['abcd', 786, 2.23, 'runoob', 70.2]
abcd
[786, 2.23]
[2.23, 'runoob', 70.2]
[123, 'runoob', 123, 'runoob']
['abcd', 786, 2.23, 'runoob', 70.2, 123, 'runoob']
```
与Python字符串不一样的是列表中的元素是可以改变的
```python
>>> a = [1, 2, 3, 4, 5, 6]
>>> a[0] = 9
>>> a[2:5] = [13, 14, 15]
>>> a
[9, 2, 13, 14, 15, 6]
>>> a[2:5] = [] # 将对应的元素值设置为 []
>>> a
[9, 2, 6]
```
List 内置了有很多方法,例如 append()、pop() 等等,这在后面会讲到。
**注意:**
- 1、List写在方括号之间元素用逗号隔开。
- 2、和字符串一样list可以被索引和切片。
- 3、List可以使用+操作符进行拼接。
- 4、List中的元素是可以改变的。
Python 列表截取可以接收第三个参数,参数作用是截取的步长,以下实例在索引 1 到索引 4 的位置并设置为步长为 2间隔一个位置来截取字符串
![](https://www.runoob.com/wp-content/uploads/2014/08/py-dict-1.png)
如果第三个参数为负数表示逆向读取,以下实例用于翻转字符串:
```python
def reverseWords(input):
# 通过空格将字符串分隔符,把各个单词分隔为列表
inputWords = input.split(" ")
# 翻转字符串
# 假设列表 list = [1,2,3,4],
# list[0]=1, list[1]=2 ,而 -1 表示最后一个元素 list[-1]=4 ( 与 list[3]=4 一样)
# inputWords[-1::-1] 有三个参数
# 第一个参数 -1 表示最后一个元素
# 第二个参数为空,表示移动到列表末尾
# 第三个参数为步长,-1 表示逆向
inputWords=inputWords[-1::-1]
# 重新组合字符串
output = ' '.join(inputWords)
return output
if __name__ == "__main__":
input = 'I like runoob'
rw = reverseWords(input)
print(rw)
```
输出结果为:
```runoob like I ```
## Tuple元组
元组tuple与列表类似不同之处在于元组的元素不能修改。元组写在小括号 () 里,元素之间用逗号隔开。
元组中的元素类型也可以不相同:
```python
#!/usr/bin/python3
tuple = ( 'abcd', 786 , 2.23, 'runoob', 70.2 )
tinytuple = (123, 'runoob')
print (tuple) # 输出完整元组
print (tuple[0]) # 输出元组的第一个元素
print (tuple[1:3]) # 输出从第二个元素开始到第三个元素
print (tuple[2:]) # 输出从第三个元素开始的所有元素
print (tinytuple * 2) # 输出两次元组
print (tuple + tinytuple) # 连接元组
```
以上实例输出结果:
```('abcd', 786, 2.23, 'runoob', 70.2)
abcd
(786, 2.23)
(2.23, 'runoob', 70.2)
(123, 'runoob', 123, 'runoob')
('abcd', 786, 2.23, 'runoob', 70.2, 123, 'runoob')
```
元组与字符串类似可以被索引且下标索引从0开始-1 为从末尾开始的位置。也可以进行截取(看上面,这里不再赘述)。
其实,可以把字符串看作一种特殊的元组。
``` python
>>> tup = (1, 2, 3, 4, 5, 6)
>>> print(tup[0])
1
>>> print(tup[1:5])
(2, 3, 4, 5)
>>> tup[0] = 11 # 修改元组元素的操作是非法的
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>>
```
虽然tuple的元素不可改变但它可以包含可变的对象比如list列表。
构造包含 0 个或 1 个元素的元组比较特殊,所以有一些额外的语法规则:
```tup1 = () # 空元组```
```tup2 = (20,) # 一个元素,需要在元素后添加逗号```
string、list 和 tuple 都属于 sequence序列
**注意:**
- 1、与字符串一样元组的元素不能修改。
- 2、元组也可以被索引和切片方法一样。
- 3、注意构造包含 0 或 1 个元素的元组的特殊语法规则。
- 4、元组也可以使用+操作符进行拼接。
## Set集合
集合set是由一个或数个形态各异的大小整体组成的构成集合的事物或对象称作元素或是成员。
基本功能是进行成员关系测试和删除重复元素。
可以使用大括号``` { } ```或者 ```set()``` 函数创建集合,注意:创建一个空集合必须用``` set() ```而不是``` { }```,因为``` { }``` 是用来创建一个空字典。
创建格式:
``` python
parame = {value01,value02,...}
或者
set(value)
```
实例:
```python
#!/usr/bin/python3
sites = {'Google', 'Taobao', 'Runoob', 'Facebook', 'Zhihu', 'Baidu'}
print(sites) # 输出集合,重复的元素被自动去掉
# 成员测试
if 'Runoob' in sites :
print('Runoob 在集合中')
else :
print('Runoob 不在集合中')
# set可以进行集合运算
a = set('abracadabra')
b = set('alacazam')
print(a)
print(a - b) # a 和 b 的差集
print(a | b) # a 和 b 的并集
print(a & b) # a 和 b 的交集
print(a ^ b) # a 和 b 中不同时存在的元素
```
以上实例输出结果:
```python
{'Zhihu', 'Baidu', 'Taobao', 'Runoob', 'Google', 'Facebook'}
Runoob 在集合中
{'b', 'c', 'a', 'r', 'd'}
{'r', 'b', 'd'}
{'b', 'c', 'a', 'z', 'm', 'r', 'l', 'd'}
{'c', 'a'}
{'z', 'b', 'm', 'r', 'l', 'd'}
```
## Dictionary字典
字典dictionary是Python中另一个非常有用的内置数据类型。
列表是有序的对象集合,字典是无序的对象集合。两者之间的区别在于:字典当中的元素是通过键来存取的,而不是通过偏移存取。
字典是一种映射类型,字典用``` { } ```标识,它是一个无序的 **键(key) : 值(value)** 的集合。
键(key)必须使用不可变类型。
在同一个字典中,键(key)必须是唯一的。
**实例:**
```python
#!/usr/bin/python3
dict = {}
dict['one'] = "1 - 菜鸟教程"
dict[2] = "2 - 菜鸟工具"
tinydict = {'name': 'runoob','code':1, 'site': 'www.runoob.com'}
print (dict['one']) # 输出键为 'one' 的值
print (dict[2]) # 输出键为 2 的值
print (tinydict) # 输出完整的字典
print (tinydict.keys()) # 输出所有键
print (tinydict.values()) # 输出所有值
```
以上实例输出结果:
```python
1 - 菜鸟教程
2 - 菜鸟工具
{'name': 'runoob', 'code': 1, 'site': 'www.runoob.com'}
dict_keys(['name', 'code', 'site'])
dict_values(['runoob', 1, 'www.runoob.com'])
```
构造函数 dict() 可以直接从键值对序列中构建字典如下:
**实例:**
```python
>>> dict([('Runoob', 1), ('Google', 2), ('Taobao', 3)])
{'Runoob': 1, 'Google': 2, 'Taobao': 3}
>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}
>>> dict(Runoob=1, Google=2, Taobao=3)
{'Runoob': 1, 'Google': 2, 'Taobao': 3}
>>>
```
另外字典类型也有一些内置的函数例如clear()、keys()、values()等。
注意:
- 1、字典是一种映射类型它的元素是键值对。
- 2、字典的关键字必须为不可变类型且不能重复。
- 3、创建空字典使用 { }。
## Python数据类型转换
有时候,我们需要对数据内置的类型进行转换,数据类型的转换,你只需要将数据类型作为函数名即可。
以下几个内置的函数可以执行数据类型之间的转换。这些函数返回一个新的对象,表示转换的值。
|函数 |描述|
|-------|-------|
|int(x [,base])|将x转换为一个整数|
|float(x))|将x转换到一个浮点数|
|complex(real [,imag])|创建一个复数|
|str(x)|将对象 x 转换为字符串|
|repr(x)|将对象 x 转换为表达式字符串|
|eval(str)|用来计算在字符串中的有效Python表达式,并返回一个对象|
|tuple(s)|将序列 s 转换为一个元组|
|list(s) |将序列 s 转换为一个列表 |
|set(s) |转换为可变集合|
|dict(d) |创建一个字典。d 必须是一个 (key, value)元组序列。 |
|frozenset(s) |转换为不可变集合 |
|chr(x) |将一个整数转换为一个字符 |
|ord(x) |将一个字符转换为它的整数值 |
|hex(x) |将一个整数转换为一个十六进制字符串 |
|oct(x) |将一个整数转换为一个八进制字符串 |

@ -0,0 +1,45 @@
---
icon: edit
date: 2021-09-20
category:
- python
tag:
- python
- 注释
headerDepth: 5
---
# Python3 注释
# Python3 注释
确保对模块, 函数, 方法和行内注释使用正确的风格
Python中的注释有单行注释和多行注释
Python中单行注释以 # 开头,例如::
```python
# 这是一个注释
print("Hello, World!")
```
多行注释用三个单引号 ''' 或者三个双引号 """ 将注释括起来,例如:
## 1、单引号'''
```python
#!/usr/bin/python3
'''
这是多行注释,用三个单引号
这是多行注释,用三个单引号
这是多行注释,用三个单引号
'''
print("Hello, World!")
```
## 2、双引号"""
```python
#!/usr/bin/python3
"""
这是多行注释,用三个双引号
这是多行注释,用三个双引号
这是多行注释,用三个双引号
"""
print("Hello, World!")
```

@ -0,0 +1,108 @@
---
icon: edit
date: 2021-09-20
category:
- python
- Linux
tag:
- python
headerDepth: 5
---
# Python3 解释器
# Python3 解释器
Linux/Unix的系统上一般默认的 python 版本为 2.x我们可以将 python3.x 安装在 /usr/local/python3 目录中。
安装完成后,我们可以将路径 /usr/local/python3/bin 添加到您的 Linux/Unix 操作系统的环境变量中,这样您就可以通过 shell 终端输入下面的命令来启动 Python3 。
>Python 解释器可不止一种哦,有 CPython、IPython、Jython、PyPy 等。
>顾名思义CPython 就是用 C 语言开发的了,是官方标准实现,拥有良好的生态,所以应用也就最为广泛了。
>而 IPython 是在 CPython 的基础之上在交互式方面得到增强的解释器http://ipython.org/)。
>Jython 是专为 Java 平台设计的 Python 解释器http://www.jython.org/),它把 Python 代码编译成 Java 字节码执行。
>PyPy 是 Python 语言2.7.13和3.5.3的一种快速、兼容的替代实现http://pypy.org/),以速度快著称。
```shell
$ PATH=$PATH:/usr/local/python3/bin/python3 # 设置环境变量
$ python3 --version
Python 3.4.0
```
在Window系统下你可以通过以下命令来设置Python的环境变量假设你的Python安装在 C:\Python34 下:
```doc
set path=%path%;C:\python34
```
## 交互式编程
我们可以在命令提示符中输入"Python"命令来启动Python解释器
```shell
$ python3
```
执行以上命令后,出现如下窗口信息:
```shell
$ python3
Python 3.4.0 (default, Apr 11 2014, 13:05:11)
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
```
在 python 提示符中输入以下语句,然后按回车键查看运行效果:
```shell
print ("Hello, Python!");
```
以上命令执行结果如下:
```shell
Hello, Python!
```
当键入一个多行结构时,续行是必须的。我们可以看下如下 if 语句:
```shell
>>> flag = True
>>> if flag :
... print("flag 条件为 True!")
...
flag 条件为 True!
```
## 脚本式编程
将如下代码拷贝至 hello.py文件中
```shell
print ("Hello, Python!");
```
通过以下命令执行该脚本:
```shell
python3 hello.py
```
输出结果为:
```shell
Hello, Python!
```
在Linux/Unix系统中你可以在脚本顶部添加以下命令让Python脚本可以像SHELL脚本一样可直接执行
```shell
#! /usr/bin/env python3.
```
然后修改脚本权限,使其有执行权限,命令如下:
```
$ chmod +x hello.py
```
**关于chmod命令请看** [Linux chmod命令](http://wuanwanghao.top/archives/linuxchmod%E5%91%BD%E4%BB%A4)
执行以下命令:
```
./hello.py
```
输出结果为:
```shell
Hello, Python!
```

@ -0,0 +1,88 @@
---
icon: edit
date: 2022-10-25
category:
- Rust
headerDepth: 5
---
# Rust 文件加解密
```Cargo.toml```
```toml
[dependencies]
aes = "0.7.5"
block-modes = "0.8.1"
hex-literal = "0.2.1"
rand = "0.8.4"
bytebuffer = "0.2.1"
base64 = "0.13.0"
```
main.rs
```rust
use aes::Aes256;
use block_modes::{BlockMode, Cbc};
use block_modes::block_padding::Pkcs7;
use rand::seq::SliceRandom;
use std::fs;
type AesCbc = Cbc<Aes256, Pkcs7>;
use std::fs::File;
use std::io::prelude::*;
const BASE_STR: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const KEY:&str = "01234567012345670123456701234567";
fn gen_ascii_chars(size: usize) -> String {
let mut rng = &mut rand::thread_rng();
String::from_utf8(
BASE_STR.as_bytes()
.choose_multiple(&mut rng, size)
.cloned()
.collect()
).unwrap()
}
fn encrypt(key: &str, data: &[u8]) -> String {
let iv_str = gen_ascii_chars(16);
let iv = iv_str.as_bytes();
let cipher = AesCbc::new_from_slices(key.as_bytes(), iv).unwrap();
let ciphertext = cipher.encrypt_vec(data);
let mut buffer = bytebuffer::ByteBuffer::from_bytes(iv);
buffer.write_bytes(&ciphertext);
base64::encode(buffer.to_bytes())
}
fn decrypt(key: &str, data: &str) -> String {
let bytes = base64::decode(data).unwrap();
let cipher = AesCbc::new_from_slices(key.as_bytes(), &bytes[0..16]).unwrap();
String::from_utf8_lossy(cipher.decrypt_vec(&bytes[16..]).unwrap().as_slice()).to_string()
}
fn decryptToByte(key: &str, data: &str) -> Vec<u8> {
let bytes = base64::decode(data).unwrap();
let cipher = AesCbc::new_from_slices(key.as_bytes(), &bytes[0..16]).unwrap();
cipher.decrypt_vec(&bytes[16..]).unwrap()
}
fn encodefile(path:&str,encodePath:&str){
//let plaintext = "hello worldsssss";
let plaintext = fs::read(path).unwrap();
let classstr = String::from_utf8_lossy(plaintext.as_slice()).to_string();
let enc = encrypt(KEY, plaintext.as_slice());
// println!("{}", enc);
let dec = decrypt(KEY, &enc);
assert_eq!(classstr, dec);
// println!("{}", dec);
let mut file = File::create(encodePath).unwrap();
file.write(enc.as_bytes()).unwrap();
}
fn decodefile(path:&str,decodePath:&str){
let plaintext = fs::read(path).unwrap();
let classstr = String::from_utf8_lossy(plaintext.as_slice()).to_string();
// let dec = decrypt(key, &classstr);
let decodeBytes = decryptToByte(KEY,&classstr);
let mut file = File::create(decodePath).unwrap();
file.write(decodeBytes.as_slice()).unwrap();
}
fn main() {
encodefile("C:\\Users\\61778\\Desktop\\HelloWorld.class","C:\\Users\\61778\\Desktop\\test1\\HelloWorldDE.class");
decodefile("C:\\Users\\61778\\Desktop\\test1\\HelloWorldDE.class","C:\\Users\\61778\\Desktop\\test1\\HelloWorld.class");
}
```

@ -0,0 +1,99 @@
---
icon: edit
date: 2023-04-06
category:
- Linux
tag:
- scp
headerDepth: 5
---
# SCP 命令详解
## 一、示例
1. 从本地复制到远程
在本地服务器上将/root/lk目录下所有的文件传输到服务器43.224.34.73的/home/lk/cpfile目录下命令为
```shell
scp -r /root/lk root@43.224.34.73:/home/lk/cpfile
```
2. 从远程复制到本地
在本地服务器上操作将服务器43.224.34.73上/home/lk/目录下所有的文件全部复制到本地的/root目录下命令为
```shell
scp -r root@43.224.34.73:/home/lk /root
```
## 二、命令详解
> scp是secure copy的简写用于在Linux下进行远程拷贝文件的命令和它类似的命令有cp不过cp只是在本机进行拷贝不能跨服务器而且scp传输是加密的。
> 可能会稍微影响一下速度。当你服务器硬盘变为只读 read only system时用scp可以帮你把文件移出来。
> 另外scp还非常不占资源不会提高多少系统负荷在这一点上rsync就远远不及它了。虽然 rsync比scp会快一点但当小文件众多的情况下rsync会导致硬盘I/O非常高而scp基本不影响系统正常使用。
### 1命令格式
scp [参数] [原路径] [目标路径]
### 2命令功能
scp是 secure copy的缩写, scp是linux系统下基于ssh登陆进行安全的远程文件拷贝命令。linux的scp命令可以在linux服务器之间复制文件和目录。
### 3命令参数
>-1 强制scp命令使用协议ssh1
-2 强制scp命令使用协议ssh2
-4 强制scp命令只使用IPv4寻址
-6 强制scp命令只使用IPv6寻址
-B 使用批处理模式(传输过程中不询问传输口令或短语)
-C 允许压缩。(将-C标志传递给ssh从而打开压缩功能
-p 保留原文件的修改时间,访问时间和访问权限。
-q 不显示传输进度条。
-r 递归复制整个目录。
-v 详细方式显示输出。scp和ssh(1)会显示出整个过程的调试信息。这些信息用于调试连接,验证和配置问题。
-c cipher 以cipher将数据传输进行加密这个选项将直接传递给ssh。
-F ssh_config 指定一个替代的ssh配置文件此参数直接传递给ssh。
-i identity_file 从指定文件中读取传输时使用的密钥文件此参数直接传递给ssh。
-l limit 限定用户所能使用的带宽以Kbit/s为单位。
-o ssh_option 如果习惯于使用ssh_config(5)中的参数传递方式,
-P port 注意是大写的P, port是指定数据传输用到的端口号
-S program 指定加密传输时所使用的程序。此程序必须能够理解ssh(1)的选项。
### 4使用实例
scp命令的实际应用概述
从本地服务器复制到远程服务器:
#### (1) 复制文件
命令格式:
```shell
scp local_file remote_username@remote_ip:remote_folder
```
或者
```shell
scp local_file remote_username@remote_ip:remote_file
```
或者
```shell
scp local_file remote_ip:remote_folder
```
或者
```shell
scp local_file remote_ip:remote_file
```
>第1,2个指定了用户名命令执行后需要输入用户密码第1个仅指定了远程的目录文件名字不变第2个指定了文件名
>第3,4个没有指定用户名命令执行后需要输入用户名和密码第3个仅指定了远程的目录文件名字不变第4个指定了文件名
#### (2) 复制目录
命令格式:
```shell
scp -r local_folder remote_username@remote_ip:remote_folder
```
或者
```shell
scp -r local_folder remote_ip:remote_folder
```
>第1个指定了用户名命令执行后需要输入用户密码。
>第2个没有指定用户名命令执行后需要输入用户名和密码。

@ -0,0 +1,16 @@
---
icon: edit
date: 2021-10-18
tag:
- SpringCloud
headerDepth: 5
---
# Spring Cloud 一些组件 网上自建项目地址
## 注册中心
### nacos
>[nacos](http://114.115.184.124:8848/nacos)
## 流控中心
### sentinel
>[sentinel](http://114.115.184.124:8858/)

@ -0,0 +1,13 @@
---
icon: edit
date: 2022-07-04
category:
- 内网穿透
headerDepth: 5
---
# Windows 10上开启路由转发
[打开windows路由转发功能](https://docker.blog.csdn.net/article/details/11700553?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-11700553-blog-122132109.pc_relevant_multi_platform_whitelistv2&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-11700553-blog-122132109.pc_relevant_multi_platform_whitelistv2&utm_relevant_index=1)
[Windows 10上开启路由转发及添加路由](https://blog.csdn.net/weixin_44647835/article/details/109616688?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-109616688-blog-11700553.pc_relevant_multi_platform_whitelistv1&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-109616688-blog-11700553.pc_relevant_multi_platform_whitelistv1&utm_relevant_index=1)

@ -0,0 +1,43 @@
---
icon: edit
date: 2021-11-26
category:
- 系统配置
tag:
- frp
headerDepth: 5
---
# Windows设置frpc开机自动启动(不管用户是否登陆都要运行)
### 新建start.bat,内容如下(放到自己frpc实际目录下):
```shell
@echo off
:home
frpc -c frpc.ini
goto home
```
### 打开开始菜单,输入 “任务计划程序” 将会自动搜索,接着打开它。![](https://img-blog.csdnimg.cn/20200929111009349.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2dkYWxp,size_16,color_FFFFFF,t_70)
点击右侧的 “创建任务”,名称随意填写,安全选项选择 “不管用户是否登录都要运行”,当然你也可以选择 “只在用户登录时运行”。
选择 “不管用户是否登录都要运行” 可以让你的电脑在断电自动启动后自动运行 frp你就可以远程桌面连接电脑了。
“使用最高权限运行” 也是可选的,根据个人需要可以选上。
最后勾选 “隐藏”,就不会在启动时弹出命令行窗口了。
![](https://img-blog.csdnimg.cn/20200929111043192.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2dkYWxp,size_16,color_FFFFFF,t_70)
接着转到 “触发器” 页,点击新建,选择 “启动时”
![](https://img-blog.csdnimg.cn/20200929111107766.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2dkYWxp,size_16,color_FFFFFF,t_70)
接着转到 “操作” 页,点击新建,选择 “启动程序”
在程序或脚本一栏选择第一步创建的 start.bat下面的 “起始于” 填写 start.bat 的路径(不要包含 start.bat
例如你的 start.bat 在 E:\frp\start.bat那么你只需要在 “起始于” 填写 E:\frp\
![](https://img-blog.csdnimg.cn/20200929111151748.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2dkYWxp,size_16,color_FFFFFF,t_70)
接着返回 “常规” 页,点击确定,此时会要求输入密码,输入你的电脑密码,然后点击确定即可。
以后就会开机自动启动 frp 了,并且不会弹出命令提示符窗口。

@ -0,0 +1,69 @@
---
icon: edit
date: 2023-04-11
category:
- Linux
tag:
- alist
- raidrive
headerDepth: 5
---
# alist 和 raidrive 组建本地网络硬盘
[alist 官网](https://alist.nn.ci/)
[raidrive 官网](https://www.raidrive.com/)
### 下载安装
[AList Release](https://github.com/Xhofe/alist/releases) 下载自己需要的版本
```bash
# 解压下载的文件,得到可执行文件:
tar -zxvf alist-xxxx.tar.gz
# 授予程序执行权限:
chmod +x alist
# 运行程序
./alist server
# 获得管理员信息
./alist admin
```
### 守护进程
使用任意方式编辑 `/usr/lib/systemd/system/alist.service` 并添加如下内容,其中 path_alist 为 AList 所在的路径
```ini
[Unit]
Description=alist
After=network.target
[Service]
Type=simple
WorkingDirectory=path_alist
ExecStart=path_alist/alist server
Restart=on-failure
[Install]
WantedBy=multi-user.target
```
然后,执行 `systemctl daemon-reload` 重载配置,现在你可以使用这些命令来管理程序:
- 启动: `systemctl start alist`
- 关闭: `systemctl stop alist`
- 配置开机自启: `systemctl enable alist`
- 取消开机自启: `systemctl disable alist`
- 状态: `systemctl status alist`
- 重启: `systemctl restart alist`
### raidrive 下载安装
windows 下
[raidrive 官网](https://www.raidrive.com/) 下载radrive 安装包安装
安装完成后
点击```添加``` 选择```NAS``` 选择```WebDAV```
根据需要添加是否时https 选择 不是就把 地址框的对勾取消
输入alist 地址 和端口
输入alist 账号 密码
![image-1681204409171](https://local.wuanwanghao.top:9000/test/test/image-1681204409171.png)

@ -0,0 +1,84 @@
---
icon: edit
date: 2023-04-12
category:
- 开发工具
- Linux
tag:
- onlyoffice
- zfile
headerDepth: 5
---
# alist 对接onlyoffice docker onlyoffice搭建和在线编辑实现
### docker 搭建onlyoffice 目前不能在arch linux 环境中使用,各种情况可以参考onlyoffcie github issue
选用版本7.1.1 因为此版本不会强制jwt 校验
```
docker run --restart=always --name onlyoffice \
-p 8081:80 \
-e JWT_ENABLED=false \
-v /app/onlyoffice/DocumentServer/logs:/var/log/onlyoffice \
-v /app/onlyoffice/DocumentServer/data:/var/www/onlyoffice/Data \
-v /app/onlyoffice/DocumentServer/lib:/var/lib/onlyoffice \
-v /app/onlyoffice/DocumentServer/db:/var/lib/postgresql \
onlyoffice/documentserver:7.1.1
```
nginx 需要给onlyoffice 代理 SSL 配置的话请添加
```
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $host:$server_port;
```
部署完成后需要自己nginx 在静态代理一个页面view.html
其中的```https:/onlyoffice/web-apps/apps/api/documents/api.js``` 地址的domain 替换为自己onlyoffice 的地址
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>OnlyOffice Viewer</title>
</head>
<body>
<div id="placeholder"></div>
<script type="text/javascript" src="https:/onlyoffice/web-apps/apps/api/documents/api.js"></script>
<script>
function getQueryParamValue(name) {
const searchParams = new URLSearchParams(window.location.search);
return searchParams.get(name);
}
const url = decodeURIComponent(getQueryParamValue("src"));
const fileName = url.substring(url.lastIndexOf('/') + 1, url.lastIndexOf('?') != -1 ? url.lastIndexOf('?') : url.length);
const fileExtension = fileName.split('.').pop();
const docEditor = new DocsAPI.DocEditor("placeholder", {
"document": {
"fileType": fileExtension,
"permissions": {
"edit": false,
"comment": true,
"download": true,
"print": true,
"fillForms": true,
},
"title": fileName,
"url": url,
},
"editorConfig": {
"lang": "zh-CN",
"mode": "view",
},
"height": "1080px",
"type": "desktop",
});
</script>
</body>
</html>
```
### nginx 代理完静态页面后 将地址配置到alist 里面就可以使用了
![image-1681290100978](https://local.wuanwanghao.top:9000/test/test/image-1681290100978.png)
### onlyoffice使用文件编辑的话选用 ,参照此[issue](https://github.com/alist-org/alist/discussions/3899)

@ -0,0 +1,71 @@
---
icon: edit
date: 2023-01-06
category:
- cpp
tag:
- 初始化问题
headerDepth: 5
---
# c++ 不规范初始化时,出现的一系列奇怪问题解决(引发了异常 读取访问权限冲突)
**今天公司的c++ 项目,需要加一下小功能,读取配置,控制业务功能开启**
#### 问题原因
这是有一段main 方法内的代码块 nacos 初始化并注册的代码
```cpp
nacos::Nacos nacos(GetIpAddress().value(), PORT, NACOS_APPNAME);
nacos.namespaceId = NACOS_NAMESPACEID;
nacos::NacosClient cli(&nacos);
cli.registerNacos();
```
但是如果加上if 之后 或者代码提出来到外部方法内 就会出现问题了
```cpp
if(flag){
nacos::Nacos nacos(GetIpAddress().value(), PORT, NACOS_APPNAME);
nacos.namespaceId = NACOS_NAMESPACEID;
nacos::NacosClient cli(&nacos);
cli.registerNacos();
}
void run(){
nacos::Nacos nacos(GetIpAddress().value(), PORT, NACOS_APPNAME);
nacos.namespaceId = NACOS_NAMESPACEID;
nacos::NacosClient cli(&nacos);
cli.registerNacos();
}
```
就会出现 引发了异常: **读取访问权限冲突 问题**
图片就不粘贴了
这里开了个线程跑了个方法监听发送心跳检测
```cpp
void nacos::NacosClient::beatNacos()
{
pthread_create(&beatNacosThread, NULL, action::BeatNacosThread, this);
}
void* BeatNacosThread(void* args) {
NacosClient& cli = *(NacosClient*)args;
Nacos *nacos = cli.getNacos();
```
就在这一段出现的问题 BeatNacosThread 方法的 参数 传递的是NacosClient 指针,但是指针指向的堆空间损坏了。方法内读取参数就会出现(读取访问权限冲突问题)
#### 问题解决
其实也很简单: 使用new 实例化
```cpp
nacos::Nacos *nacos = new Nacos(LOCAL_IP, PORT, NACOS_APPNAME);
nacos->namespaceId = NACOS_NAMESPACEID;
nacos::NacosClient *cli = new NacosClient(nacos);
cli->registerNacos();
cli->getNacosConfig();
cli->listenNacosConfig();
```
#### 问题总结
默认的实例化方式是其实调用的**c 的 malloc 函数** malloc 函数实例化的对象堆的内存空间是动态的,如果方法执行完成 或者 在if 语句块也是同样的原理,方法内的对象 或 if 语句块中的对象 内存就会损坏, 但是如果用 new 的话 创建的对象堆内存不是动态的。方法执行完毕也不会损坏。清理空间方法是使用 delete 关键字。
参考资料
[读取字符串的字符时出错 无法读取内存](https://blog.csdn.net/fb_941219/article/details/106968262?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-106968262-blog-104897719.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-106968262-blog-104897719.pc_relevant_default&utm_relevant_index=1)
[vs debug模式下显示“变量已被优化掉因而不可用”的解决办法](https://blog.csdn.net/weixin_44120025/article/details/115279323)
[C中的malloc和free释放原理](https://blog.csdn.net/qq_34272143/article/details/122594250)
[c++调试出现“读取字符串的字符时出错”,无法读取内存? 以及malloc函数和new 的区别](https://www.cnblogs.com/MYJ55/p/6765587.html)

@ -0,0 +1,33 @@
---
icon: edit
date: 2023-01-11
category:
- 系统配置
- cpp
tag:
- 操作符
- 重载
headerDepth: 5
---
# c++ 能重载的操作符有那些
重载操作符是指重新定义C++中已有运算符的含义。常见的重载操作符有:
```
算术运算符: +, -, *, /, %
关系运算符: ==, !=, >, <, >=, <=
逻辑运算符: &&, ||, !
赋值运算符: =
位运算符: &, |, ^, ~, <<, >>
自增/自减运算符: ++, --
成员访问运算符: ->, .
下标运算符: [ ]
函数调用运算符: ( )
转型运算符: (type)
new 和 delete 运算符: new, delete, new[], delete[]
另外还有三个特殊的运算符是可以被重载的:
复合赋值运算符: +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
串联运算符: <<, >>
逗号运算符: ,
```
需要注意的是所有运算符重载都需要在类内部进行,且实现的时候可能需要使用特殊的关键字来实现,如 ```friend``` 和 ```operator```.

@ -0,0 +1,37 @@
---
icon: edit
date: 2022-12-02
category:
- 系统配置
- Linux
headerDepth: 5
---
# centos7 更改用户组
```这里都是root权限下执行你也可以加上sudo```
```shell
cat /etc/group
```
或者使用管道直接选出是否docker
```shell
cat /etc/group grep docker
```
如果出现docker就不用添加有时会出现dockerroot没做研究我也添加docker用户组。
第二步添加docker用户组
```shell
groupadd docker
```
也可以指定用户组id修改id就可以不要和第一个查出来的id重复
```shell
groupadd -g id docker
```
第三步把普通用户添加docker用户组
```shell
gpasswd -a 普通用户名 docker
```
第四 更新用户组
```shell
newgrp docker
```

@ -0,0 +1,71 @@
---
icon: edit
date: 2023-01-16
category:
- 系统配置
- cpp
tag:
- CMake
headerDepth: 5
---
# cmake 命令详解
#### Cmake命令行使用:
```shell
-G 指明生成的Makefile 的生成器
-D 添加参数
-S 指明源码位置
-B 指明输出路径
-A 指定系统架构
-U 标志可用于取消设置变量
```
例如:
```
cmake -G "MinGW Makefiles" -S "源码路径" -B "输出路径"
```
或者
```
cmake -G "MinGW Makefiles" -DCMAKE_TOOLCHAIN_FILE="编译工具链路径" -S "源码路径" -B "输出路径"
```
**注意:Cmake是不支持中文的,无论是GUI还是命令行,都严禁出现中文字符.**
#### -G 命令详解
##### 一、介绍
CMake默认根据平台选择一个生成器。通常默认生成器足以让用户继续构建软件。用户可以使用-G选项覆盖默认生成器:
```shell
$ cmake .. -G Ninja
```
1. cmake --help的输出包括一个可供用户选择的生成器列表。注意生成器名称是区分大小写的
![image-1673858124577](https://local.wuanwanghao.top:9000/test/test/image-1673858124577.png)
2. 项目构建工具
类似make的工具有 ```Ninja``` 、```nmake``` 、```devenvvs```。
makefile 可以理解为是make工具使用的代码make读取makefile中的配置信息来实现编译、链接和部署。
![image-1673858287897](https://local.wuanwanghao.top:9000/test/test/image-1673858287897.png)
##### -G 细节
在类Unix系统(包括Mac OS X)上默认情况下使用Unix Makefiles生成器。该生成器的一个变体也可以在Windows的各种环境中使用比如NMake Makefiles和MinGW Makefiles生成器。这些生成器生成一个Makefile变量可以用make、gmake、nmake或类似的工具执行
而Visual Studio生成器可以针对不同的体系结构。可以使用-A选项指定目标架构:
```shell
cmake .. -G "Visual Studio 2019" -A x64
cmake .. -G "Visual Studio 16" -A ARM
cmake .. -G "Visual Studio 16 2019" -A ARM64
```
请注意在第一次调用CMake之后不可能使用-G来更改生成器。要更改生成器必须删除构建目录并且必须从头开始构建。
#### -D 命令详解
```
CMAKE_INSTALL_PREFIX #设置构建完成的安装路径
CMAKE_TOOLCHAIN_FILE #编译工具链路径
CMAKE_PREFIX_PATH #搜索路径 dependent packages
CMAKE_MODULE_PATH #搜索其他 CMake 模块的路径
CMAKE_BUILD_TYPE #构建配置,例如 Debug或Release确定调试/优化标志。这仅与单配置构建系统相关例如Makefile和Ninja。用于 Visual Studio 和 Xcode 的多配置构建系统会忽略此设置。
BUILD_SHARED_LIBS #是否构建共享库而不是静态库add_library() 没有类型的命令
CMAKE_EXPORT_COMPILE_COMMANDS #生成compile_commands.json 用于基于 clang 的工具的文件
CMAKE_MAKE_PROGRAM #可以启动本机构建系统的工具。该值可能是可执行文件的完整路径,或者只是工具名称 如果它应该位于PATH.
CMAKE_C_COMPILER #设置C的编译器
CMAKE_CXX_COMPILER #设置C++的编译器
```
CMAKE_MAKE_PROGRAM 属性值 和 -G 一般搭配使用
如果 -G 指定了 ```Ninja```生成器 那么CMAKE_MAKE_PROGRAM 就要指定Ninja 所在位置 D:/Program Files/JetBrains/CLion 2022.1.3/bin/ninja/win/ninja.exe 但 如果 ninja.exe 在环境变量中可以不指定 或者只用写ninja的名字即可

@ -0,0 +1,57 @@
---
icon: edit
date: 2023-04-02
category:
- 系统配置
- Linux
tag:
- crontab
headerDepth: 5
---
# crontab linux 定时任务工具使用
### 使用
```
crontab: usage error: unrecognized option
usage: crontab [-u user] file
crontab [ -u user ] [ -i ] { -e | -l | -r }
(default operation is replace, per 1003.2)
-e (edit user's crontab)
-l (list user's crontab)
-r (delete user's crontab)
-i (prompt before deleting user's crontab)
```
- -e 编辑和添加crontab
- -l 列出所有的定时任务
- -r 删除定时任务
- -i 删除用户crontab前提示
### crontab运行日志查看
有时候发现定时任务没有按预期执行,可以能过查看日志发现执行相关的问题。
一般来说 ```crontab```的运行日志可以在```/var/log/cron.log```文件中。
如果没有```/var/log/cron.log```文件,试一下```/var/log/cron```
### crontab为什么有时候找不到日志
需要通过配置打开crontab的日志记录功能。
通过以下方式开启crontab的日志记录功能。
```
sudo vim /etc/rsyslog.d/50-default.conf
cron.* /var/log/cron.log #将cron前面的注释符去掉
#重启rsyslog
#sudo /etc/init.d/rsyslog restart
sudo service rsyslog restart #重启rsyslog
sudo service cron restart #重启cron程度
sudo service crond restart #重启crond。 在有的系统中定时任务程序名称是crond
```
### 选择-e 时的编辑器 修改系统默认编辑器
```
select-editor
```
nano 编辑器 虽然提示说好用 其实大家学习的时候大多用习惯vim 的编辑器了我还是喜欢用vim
```
Select an editor. To change later, run 'select-editor'.
1. /bin/nano <---- easiest
2. /usr/bin/vim.basic
3. /usr/bin/vim.tiny
4. /bin/ed
```

@ -0,0 +1,27 @@
---
icon: edit
date: 2022-07-15
category:
- Docker
headerDepth: 5
---
# docker 安装 Portainer
[汉化版Portainer仓库地址](https://hub.docker.com/r/6053537/portainer-ce)
命令:
```
docker run -d --restart=always \
--name="portainer" \
-p 9100:9000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /home/wanghao/portainer-ce/data:/data \
6053537/portainer-ce
```
- ```-d``` 后台进程启动。
- ```-p 9000:9000``` 管理控制UI界面访问接口。
- ```-name portainer``` 容器名称。
- ```--restart=always``` 进程挂了自动重启比如重启docker以后自动重启portainer。
- ```-v``` 数据卷。
- ```6053537/portainer-ce``` portainer社区版汉化版镜像。

@ -0,0 +1,11 @@
---
icon: edit
date: 2022-07-15
category:
- Docker
headerDepth: 5
---
# docker 安装 emqx
[docker 安装 emqx](https://blog.csdn.net/qq_21137441/article/details/113539310)

@ -0,0 +1,23 @@
---
icon: edit
date: 2023-04-09
category:
- Docker
headerDepth: 5
---
# docker 安装 jenkins
```
docker run \
-u root \
-d \
--name jenkins \
--restart=always \
-p 8080:8080 \
-p 8888:8888 \
-p 50000:50000 \
-v /wanghao/jenkins_home:/var/jenkins_home \
-v /wanghao/env:/usr/local/env \
jenkins/jenkins:latest
```

@ -0,0 +1,27 @@
---
icon: edit
date: 2023-04-06
category:
- Docker
tag:
- zfile
headerDepth: 5
---
# docker 安装 zfile
[官方安装文档](https://docs.zfile.vip/install/os-docker/)
### 下载配置文件
```shell
curl -k -o /home/wanghao/zfile/config/application.properties https://c.jun6.net/ZFILE/application.properties
```
### 启动
``` shell
docker run -d --name=zfile --restart=always \
-p 8080:8080 \
-v /home/wanghao/zfile/db:/root/.zfile-v4/db \
-v /home/wanghao/zfile/logs:/root/.zfile-v4/logs \
-v /home/wanghao/zfile/file:/data/file \
-v /home/wanghao/zfile/config/application.properties:/root/application.properties \
zhaojun1998/zfile
```

@ -0,0 +1,120 @@
---
icon: edit
date: 2023-04-06
category:
- Docker
headerDepth: 5
---
# docker 开放远程管理portainer 添加远程docker 服务器 ,docker 开启TLS 认证
## docker 开放远程管理
### 修改docker 服务文件
```shell
vim /usr/lib/systemd/system/docker.service
```
### 启动命令后追加 ```-H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock```
```
#找到ExecStart这行 在后面加上-H tcp://0.0.0.0:2375 其它方式一会docker就挂了 而且重启无效
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
```
### 重启docker
```shell
systemctl daemon-reload
systemctl restart docker
```
### 防火墙开放端口
```
firewall-cmd --zone=public --add-port=2375/tcp --permanent
systemctl reload firewalld
```
## portainer 添加远程docker 服务器
![image-1680765916390](https://local.wuanwanghao.top:9000/test/test/image-1680765916390.png)
![image-1680766178357](https://local.wuanwanghao.top:9000/test/test/image-1680766178357.png)
## 配置Docker开启TLS认证
直接开放 Docker 2375 端口容易造成生成事故,被人入侵挖矿之类的, 所以这里开启TLS 认证来安全防护
### 生成TLS证书
创建证书生成脚本 createcert.sh放置/opt/sh目录
```
mkdir -p /opt/sh /opt/cert/docker
touch /opt/sh/createcert.sh
vim /opt/sh/createcert.sh
```
在createcret.sh添加内容
```
#!/bin/bash
set -e
if [ -z $1 ];then
echo "请输入Docker服务器的域名"
exit 0
fi
HOST=$1
mkdir -p /opt/cert/docker
cd /opt/cert/docker
openssl genrsa -aes256 -out ca-key.pem 4096
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
openssl genrsa -out server-key.pem 4096
openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr
# 配置白名单推荐配置0.0.0.0允许所有IP连接但只有证书才可以连接成功
echo subjectAltName = DNS:$HOST,IP:0.0.0.0 > extfile.cnf
openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf
openssl genrsa -out key.pem 4096
openssl req -subj '/CN=client' -new -key key.pem -out client.csr
echo extendedKeyUsage = clientAuth > extfile.cnf
openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnf
rm -v client.csr server.csr
chmod -v 0400 ca-key.pem key.pem server-key.pem
chmod -v 0444 ca.pem server-cert.pem cert.pem
```
执行 createcert.sh 脚本,生成证书放置 /opt/cert/docker 目录中
```
# wuanwanghao.top 是服务器的域名
sh /opt/sh/createcert.sh wuanwanghao.top
```
按照提示输入相关信息,密码一致,其他信息可留空,等脚本指定完成之后,可在 /opt/cert/docker 目录查看到生成的证书。
![image-1680790203577](https://local.wuanwanghao.top:9000/test/test/image-1680790203577.png)
### 配置Docker开启TLS认证
```
vim /usr/lib/systemd/system/docker.service
```
在ExecStart属性后追加
```
--tlsverify --tlscacert=/opt/cert/docker/ca.pem \
--tlscert=/opt/cert/docker/server-cert.pem \
--tlskey=/opt/cert/docker/server-key.pem \
-H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
```
### 重新加载docker配置后重启
```
systemctl daemon-reload
systemctl restart docker
```
查看2376端口是否启动
```
netstat -nltp | grep 2375
```
本地连接测试Docker API是否可用
没有指定证书访问测试
```
curl https://wuanwanghao.top:2375/info
```
指定证书访问测试
```
curl https://wuanwanghao.top:2375/info --cert /opt/cert/docker/cert.pem --key /opt/cert/docker/key.pem --cacert /opt/cert/docker/ca.pem
```
### portainer 重新添加docker机器
删除原先docker 机器 ,重新添加 勾选TLS 选项
![image-1680790455212](https://local.wuanwanghao.top:9000/test/test/image-1680790455212.png)
上传生成的TLS 文件
![image-1680790603638](https://local.wuanwanghao.top:9000/test/test/image-1680790603638.png)
重新链接即可

@ -0,0 +1,441 @@
---
icon: edit
date: 2021-10-17
category:
- Docker
tag:
- Docker
- Nacos
headerDepth: 5
---
# docker 部署 nacos 集群
# docker 部署 nacos 集群
>[官网部署文档](https://github.com/nacos-group/nacos-docker/blob/master/README_ZH.md)
## 编写cluster-ip.yaml
```yml
version: "2"
services:
nacos1:
image: nacos/nacos-server:latest
container_name: nacos1
networks:
nacos_net:
ipv4_address: 172.16.238.10
volumes:
- ./cluster-logs/nacos1:/home/nacos/logs
ports:
# - "8848:8848"
- "9848:9848"
- "9555:9555"
env_file:
- ../env/nacos-ip.env
restart: on-failure
nacos2:
image: nacos/nacos-server:latest
container_name: nacos2
networks:
nacos_net:
ipv4_address: 172.16.238.11
volumes:
- ./cluster-logs/nacos2:/home/nacos/logs
ports:
# - "8849:8848"
- "9849:9848"
env_file:
- ../env/nacos-ip.env
restart: always
nacos3:
image: nacos/nacos-server:latest
container_name: nacos3
networks:
nacos_net:
ipv4_address: 172.16.238.12
volumes:
- ./cluster-logs/nacos2:/home/nacos/logs
ports:
#- "8850:8848"
- "9850:9848"
env_file:
- ../env/nacos-ip.env
restart: always
networks:
nacos_net:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.16.238.0/24
```
## 编写 nacos-ip.env
``` env
#nacos dev env
NACOS_SERVERS=172.16.238.10:8848 172.16.238.11:8848 172.16.238.12:8848
MYSQL_SERVICE_HOST=114.115.184.124
MYSQL_SERVICE_DB_NAME=nacos
MYSQL_SERVICE_PORT=3307
MYSQL_SERVICE_USER=root
MYSQL_SERVICE_PASSWORD=123456
JVM_XMN=64m #年轻代大小
JVM_XMS=128m #初始堆大小
JVM_XMX=128m #最大堆大小
```
### nacos数据库sql
``` sql
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info */
/******************************************/
CREATE TABLE `config_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(255) DEFAULT NULL,
`content` longtext NOT NULL COMMENT 'content',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
`app_name` varchar(128) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
`c_desc` varchar(256) DEFAULT NULL,
`c_use` varchar(64) DEFAULT NULL,
`effect` varchar(64) DEFAULT NULL,
`type` varchar(64) DEFAULT NULL,
`c_schema` text,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info_aggr */
/******************************************/
CREATE TABLE `config_info_aggr` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(255) NOT NULL COMMENT 'group_id',
`datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
`content` longtext NOT NULL COMMENT '内容',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`app_name` varchar(128) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info_beta */
/******************************************/
CREATE TABLE `config_info_beta` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL COMMENT 'content',
`beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info_tag */
/******************************************/
CREATE TABLE `config_info_tag` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
`tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL COMMENT 'content',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_tags_relation */
/******************************************/
CREATE TABLE `config_tags_relation` (
`id` bigint(20) NOT NULL COMMENT 'id',
`tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
`tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
`nid` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`nid`),
UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = group_capacity */
/******************************************/
CREATE TABLE `group_capacity` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID空字符表示整个集群',
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额0表示使用默认值',
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限单位为字节0表示使用默认值',
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数0表示使用默认值',
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限单位为字节0表示使用默认值',
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = his_config_info */
/******************************************/
CREATE TABLE `his_config_info` (
`id` bigint(64) unsigned NOT NULL,
`nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`data_id` varchar(255) NOT NULL,
`group_id` varchar(128) NOT NULL,
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL,
`md5` varchar(32) DEFAULT NULL,
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`src_user` text,
`src_ip` varchar(50) DEFAULT NULL,
`op_type` char(10) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
PRIMARY KEY (`nid`),
KEY `idx_gmt_create` (`gmt_create`),
KEY `idx_gmt_modified` (`gmt_modified`),
KEY `idx_did` (`data_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = tenant_capacity */
/******************************************/
CREATE TABLE `tenant_capacity` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额0表示使用默认值',
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限单位为字节0表示使用默认值',
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限单位为字节0表示使用默认值',
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';
CREATE TABLE `tenant_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`kp` varchar(128) NOT NULL COMMENT 'kp',
`tenant_id` varchar(128) default '' COMMENT 'tenant_id',
`tenant_name` varchar(128) default '' COMMENT 'tenant_name',
`tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
`create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
`gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
`gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
CREATE TABLE `users` (
`username` varchar(50) NOT NULL PRIMARY KEY,
`password` varchar(500) NOT NULL,
`enabled` boolean NOT NULL
);
CREATE TABLE `roles` (
`username` varchar(50) NOT NULL,
`role` varchar(50) NOT NULL,
UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
);
CREATE TABLE `permissions` (
`role` varchar(50) NOT NULL,
`resource` varchar(255) NOT NULL,
`action` varchar(8) NOT NULL,
UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
);
INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
```
### nacos-ip.env 对应属性配置列表 可以根据需求对照填写
| 属性名称 | 描述 | 选项 |
| --------------------------------- | ------------------------------------------------------------ | ----------------------------------- |
| MODE | 系统启动方式: 集群/单机 | cluster/standalone默认 **cluster** |
| NACOS_SERVERS | 集群地址 | p1:port1空格ip2:port2 空格ip3:port3 |
| PREFER_HOST_MODE | 支持IP还是域名模式 | hostname/ip 默认 **ip** |
| NACOS_SERVER_PORT | Nacos 运行端口 | 默认 **8848** |
| NACOS_SERVER_IP | 多网卡模式下可以指定IP | |
| SPRING_DATASOURCE_PLATFORM | 单机模式下支持MYSQL数据库 | mysql / 空 默认:空 |
| MYSQL_SERVICE_HOST | 数据库 连接地址 | |
| MYSQL_SERVICE_PORT | 数据库端口 | 默认 : **3306** |
| MYSQL_SERVICE_DB_NAME | 数据库库名 | |
| MYSQL_SERVICE_USER | 数据库用户名 | |
| MYSQL_SERVICE_PASSWORD | 数据库用户密码 | |
| MYSQL_SERVICE_DB_PARAM | 数据库连接参数 | default : **characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false** |
| MYSQL_DATABASE_NUM | It indicates the number of database | 默认 :**1** |
| JVM_XMS | -Xms | 默认 :1g |
| JVM_XMX | -Xmx | 默认 :1g |
| JVM_XMN | -Xmn | 默认 :512m |
| JVM_MS | -XX:MetaspaceSize | 默认 :128m |
| JVM_MMS | -XX:MaxMetaspaceSize | 默认 :320m |
| NACOS_DEBUG | 是否开启远程DEBUG | y/n 默认 :n |
| TOMCAT_ACCESSLOG_ENABLED | server.tomcat.accesslog.enabled | 默认 :false |
| NACOS_AUTH_SYSTEM_TYPE | 权限系统类型选择,目前只支持nacos类型 | 默认 :nacos |
| NACOS_AUTH_ENABLE | 是否开启权限系统 | 默认 :false |
| NACOS_AUTH_TOKEN_EXPIRE_SECONDS | token 失效时间 | 默认 :18000 |
| NACOS_AUTH_TOKEN | token | 默认 :SecretKey012345678901234567890123456789012345678901234567890123456789 |
| NACOS_AUTH_CACHE_ENABLE | 权限缓存开关 ,开启后权限缓存的更新默认有15秒的延迟 | 默认 : false |
| MEMBER_LIST | 通过环境变量的方式设置集群地址 | 例子:192.168.16.101:8847?raft_port=8807,192.168.16.101?raft_port=8808,192.168.16.101:8849?raft_port=8809 |
| EMBEDDED_STORAGE | 是否开启集群嵌入式存储模式 | `embedded` 默认 : none |
| NACOS_AUTH_CACHE_ENABLE | nacos.core.auth.caching.enabled | default : false |
| NACOS_AUTH_USER_AGENT_AUTH_WHITE_ENABLE | nacos.core.auth.enable.userAgentAuthWhite | default : false |
| NACOS_AUTH_IDENTITY_KEY | nacos.core.auth.server.identity.key | default : serverIdentity |
| NACOS_AUTH_IDENTITY_VALUE | nacos.core.auth.server.identity.value | default : security |
| NACOS_SECURITY_IGNORE_URLS | nacos.security.ignore.urls | default : `/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**` |
## docker compose 运行 yml 文件
``` shell
docker-compose -f example/cluster-ip.yaml up
```
## nginx 配置
```conf
upstream clusterNacos{
server 172.16.238.12:8848;
server 172.16.238.11:8848;
server 172.16.238.10:8848;
}
server{
listen 8848;
server_name 114.115.184.124;
location / {
proxy_pass http://clusterNacos;
}
}
```
## 访问
![image.png](/upload/2021/10/image-39a8c8939254405f9aab2354d02f3c49.png)
#手动部署
```
# 拉取nacos
docker pull nacos/nacos-server
# 创建文件夹
mkdir -p /wanghao/nacos/logs/
mkdir -p /wanghao/nacos/init.d/
# 修改配置文件
vim /wanghao/nacos/init.d/custom.properties #修改配置文件
# mysql新建nacos的数据库并执行脚本 sql脚本地址如下
https://github.com/alibaba/nacos/blob/master/config/src/main/resources/META-INF/nacos-db.sql
# 运行nacos
docker run \
--name nacos-wh -d \
-p 8849:8848 \
--privileged=true \
--restart=always \
-e JVM_XMS=256m \
-e JVM_XMX=256m \
-e MODE=standalone \
-e PREFER_HOST_MODE=hostname \
-v /wanghao/nacos/logs:/etc/nacos/logs \
-v /wanghao/nacos/init.d/custom.properties:/etc/nacos/init.d/custom.properties \
nacos/nacos-server
```
## custom.properties
```
server.contextPath=/nacos
server.servlet.contextPath=/nacos
server.port=8848
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://114.115.184.124:3307/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=ks125930.
nacos.cmdb.dumpTaskInterval=3600
nacos.cmdb.eventTaskInterval=10
nacos.cmdb.labelTaskInterval=300
nacos.cmdb.loadDataAtStart=false
management.metrics.export.elastic.enabled=false
management.metrics.export.influx.enabled=false
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i
nacos.security.ignore.urls=/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/login,/v1/console/health/**,/v1/cs/**,/v1/ns/**,/v1/cmdb/**,/actuator/**,/v1/console/server/**
nacos.naming.distro.taskDispatchThreadCount=1
nacos.naming.distro.taskDispatchPeriod=200
nacos.naming.distro.batchSyncKeyCount=1000
nacos.naming.distro.initDataRatio=0.9
nacos.naming.distro.syncRetryDelay=5000
nacos.naming.data.warmup=true
nacos.naming.expireInstance=true
```

@ -0,0 +1,87 @@
---
icon: edit
date: 2021-11-17
category:
- Docker
tag:
- rocket-mq
headerDepth: 5
---
# docker 部署 rocket-mq
# docker 安装rocketmq
## 拉取镜像
```shell
docker pull foxiswho/rocketmq:server-4.4.0
docker pull foxiswho/rocketmq:broker-4.4.0
```
## 创建数据挂载目录
```shell
mkdir -p /wanghao/rocketmq/server/logs
mkdir -p /wanghao/rocketmq/server/store
mkdir -p /wanghao/rocketmq/broker/logs
mkdir -p /wanghao/rocketmq/broker/store
mkdir -p /wanghao/rocketmq/broker/conf
```
## 编辑配置文件
```shell
vi /wanghao/rocketmq/broker/conf/broker.conf
```
### broker.conf
```conf
namesrvAddr=服务器ip:9876
brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH
brokerIP1 = 服务器ip
listenPort=10911
```
## 创建容器
### server
```shell
docker run -p 9876:9876 \
--name rocketmq-server \
-e "JAVA_OPT_EXT=-server -Xms128m -Xmx128m -Xmn128m" \
-e "JAVA_OPTS=-Duser.home=/opt" \
-v /software/rocketmq/server/logs:/opt/logs \
-v /software/rocketmq/server/store:/opt/store \
foxiswho/rocketmq:server-4.4.0
```
### broker
```shell
docker run -it -d \
-p 10909:10909 \
-p 10911:10911 \
--name rocketmq-broker \
-e "JAVA_OPT_EXT=-server -Xms128m -Xmx128m -Xmn128m" \
-e "JAVA_OPTS=-Duser.home=/opt" \
-v /software/rocketmq/broker/conf/broker.conf:/etc/rocketmq/broker.conf \
-v /software/rocketmq/broker/logs:/opt/logs \
-v /software/rocketmq/broker/store:/opt/store \
--privileged=true \
foxiswho/rocketmq:broker-4.4.0
```
## 部署RocketMQ的管理工具
```RocketMQ提供了UI管理工具名为rocketmq-console我们选择docker安装```
### 拉取镜像
```shell
docker pull styletang/rocketmq-console-ng:1.0.0
```
### 启动容器
```shell
docker run -d \
--name rocketmq-admin \
-e "JAVA_OPTS=-Drocketmq.namesrv.addr=10.10.5.124:9876; -Dcom.rocketmq.sendMessageWithVIPChannel=false" \
-p 18080:8080 \
-t styletang/rocketmq-console-ng:1.0.0
```
![image.png](/upload/2021/11/image-883f047266bc4531af1eb96e1b588a8e.png)

@ -0,0 +1,24 @@
---
icon: edit
date: 2023-03-06
category:
- 系统配置
- Docker
headerDepth: 5
---
# docker使用ubuntu镜像图形化界面
不想用vnc安装图形化界面直接找了一个有图形化界面的ubuntu镜像
镜像地址:
https://hub.docker.com/r/kasmweb/desktop/tags
pull完镜像后生成容器即可此界面为web版地址为:
https://IP_OF_SERVER:6901
```
docker run -it -p 6901:6901 -e VNC_PW=password --name ubuntu-test kasmweb/desktop:1.10.0-rolling
```
![image-1678090052556](https://local.wuanwanghao.top:9000/test/test/image-1678090052556.png)

@ -0,0 +1,46 @@
---
icon: edit
date: 2021-09-16
category:
- Docker
tag:
- Docker
- nginx
headerDepth: 5
---
# docker部署Nginx
# Nginx的安装
## 1.下载nginx镜像
```shell
docker pull nginx
```
复制代码2.创建实例并启动
```shell
docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-d nginx:1.10
```
复制代码3.拷贝nginx的配置
>1. 将容器内的配置文件拷贝到当前目录docker container cp nginx:/etc/nginx .
>2. 修改文件名称mv nginx conf 把这个conf移动到/wanghao/nginx下
>3. 终止容器docker stop nginx
>4. 执行命令删除原容器docker rm $ContainerId
再次创建nginx容器
```shell
docker run -p 80:80 --name nginx \
--restart=always \
-v /wanghao/nginx/html:/usr/share/nginx/html \
-v /wanghao/nginx/logs:/var/log/nginx \
-v /wanghao/nginx/conf:/etc/nginx/conf.d \
-d nginx
```

@ -0,0 +1,24 @@
---
icon: edit
date: 2021-10-17
category:
- Docker
tag:
- sentinel
- Docker
headerDepth: 5
---
# docker部署sentinel
## docker 拉取 镜像
``` shell
docker pull bladex/sentinel-dashboard
```
## docker 运行 镜像
``` shell
docker run -d --name sentinel-dashboard -p 8858:8858 --restart=always bladex/sentinel-dashboard
```
## 访问sentinel
```http://ip:8858 #ip:服务器地址```
![image.png](/upload/2021/10/image-35a36703c3de4608bb87dc383d088d69.png)

@ -0,0 +1,18 @@
---
icon: edit
date: 2023-02-22
category:
- .Net
headerDepth: 5
---
# dotnet core 配置文件 相关配置 复制到编译目录
```
<ItemGroup>
<None Update="config.json"> // 需要配置的配置文件名称
// 配置复制到编译目录,文件较新就复制
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
```

@ -0,0 +1,66 @@
---
icon: edit
date: 2023-04-11
category:
- Linux
headerDepth: 5
---
# glibc 版本低的解决方法 以及升级后遇到的问题解决
centos 升级gcc 环境
```shell
yum -y install centos-release-scl
yum -y install devtoolset-8-gcc devtoolset-8-gcc-c++ devtoolset-8-binutils
scl enable devtoolset-8 bash
echo "source /opt/rh/devtoolset-8/enable" >>/etc/profile
yum install -y bison
```
升级make
```shell
wget http://ftp.gnu.org/gnu/make/make-4.2.tar.gz
tar -xzvf make-4.2.tar.gz
cd make-4.2
sudo ./configure
sudo make
sudo make install
sudo rm -rf /usr/bin/make
sudo cp ./make /usr/bin/
make -v
```
升级glibc
```shell
cd /wanghao/glibc
wget https://mirror.bjtu.edu.cn/gnu/libc/glibc-2.28.tar.xz --no-check-certificate
tar -xf glibc-2.28.tar.xz
cd glibc-2.28/
mkdir build
cd build
sudo ../configure --prefix=/usr --disable-profile --enable-add-ons --with-headers=/usr/include --with-binutils=/usr/bin
make -j 8 #make 运行时间较长 开启多线程任务编译 开启数量 8
make install
```
查看环境中所有GLIBC
```shell
ls -la /lib64/libc.so.6
strings /lib64/libc.so.6 |grep GLIBC
```
## 问题解决
### 升级libc后导致中文乱码
如果编译目录没有删除 则进入glibc的编译目录也就是build目录
```
make localedata/install-locales
```
再次执行 locale 这时应该已经正常了
但是如果你已经删除了编译glibc的build目录或者不知道build的目录在哪里
查看 locale-archive 归档文件目录
```
strings /lib64/libc-2.28.so | grep locale-archive
```
查看```目标``` 结果中有没有 locale-archive
没有就将/usr/lib/locale/locale-archive 软连接到目标位置
```
ln -s /usr/lib/locale/locale-archive 目标
```

@ -0,0 +1,36 @@
---
icon: edit
date: 2023-01-09
category:
- GoLang
- 系统配置
tag:
- GoLang
headerDepth: 5
---
# go get 遇到缓存问题解决
#### go get 遇到缓存问题解决
接手公司边缘计算项目的时候遇到的问题。公司项目包路径需要修改
当修改完重新go get 的时候,项目引入的依赖包还是旧的没有修改的
进入GOPATH 删除了那个包,再去
```shell
go mod tidy
```
发现下的包还是旧的。重复几次依旧不行这时候想到了go 使用git 命令去下的包那我是不是可以清理下git 缓存呢,尝试后已经不行。最后发现自己漏了一点,就在眼皮底下
![image-1673255828821](https://local.wuanwanghao.top:9000/test/test/image-1673255828821.png)
GOPATH 下是有个cache 目录的 进入删除vcs 文件夹 和 download 里面相应的包再去go get 问题就解决了
![image-1673255908474](https://local.wuanwanghao.top:9000/test/test/image-1673255908474.png)
**当然也有命令可以删除**
```shell
# 下载包
go get -u go clean -i github.com/werbenhu/go-tools
# 清理包
go clean -i github.com/werbenhu/go-tools...
# 清理全部包
go clean --modcache
```

@ -0,0 +1,22 @@
---
icon: edit
date: 2022-12-26
category:
- 系统配置
tag:
- grpc
- proto
headerDepth: 5
---
# grpc proto 使用 cpp 插件生成协议文件
```shell
cd D:\vcpkg\grpc_example\proto
#cmd
protoc --proto_path=. --cpp_out=. ModelGongYi.proto
protoc --proto_path=. --grpc_out=. --plugin=protoc-gen-grpc="D:\env\vcpkg\packages\grpc_x64-windows\tools\grpc\grpc_cpp_plugin.exe" ModelGongYi.proto
#poweshell
./protoc --proto_path=. --cpp_out=. calculate.proto
./protoc --proto_path=. --grpc_out=. --plugin=protoc-gen-grpc="D:\env\vcpkg\packages\grpc_x64-windows\tools\grpc\grpc_cpp_plugin.exe" calculate.proto
```

@ -0,0 +1,51 @@
---
icon: edit
date: 2022-11-14
category:
- exsi
- 系统配置
tag:
- VMDK
- 虚拟机
- 软路由
- ESXI
- img
- 固件
headerDepth: 5
---
# img 固件 转 esxi 虚拟机
#### 一、环境介绍
- ESXi版本6.5.0 (Build 4887370)
- iStoreOS版本istoreos-21.02.3-2022102715-x86-64-squashfs-combined.img.gz[koolcenter下载](https://fw.koolcenter.com/iStoreOS/)
- StarWind V2V Image Converter 链接: https://pan.baidu.com/s/1Fe6yI42Zz9d_Q7aUhGe1FQ 提取码: 5vmv
#### 二、创建虚拟机
- 1、点击“创建/注册虚拟机”,选择”创建新虚拟机“,点击“下一页”
![image-1668393862646](https://local.wuanwanghao.top:9000/test/test/image-1668393862646.png)
- 2、名称输入”istoreos“兼容性默认”ESXi 6.5 虚拟机“即可客户机操作系统系列选择”Linux“客户机操作系统版本选择”其他 3.x 或更高版本的 Linux64位或 Linux64位 “,点击“下一页”
![image-1668393923004](https://local.wuanwanghao.top:9000/test/test/image-1668393923004.png)
- 3、选择存储一般默认即可点击“下一页”
![image-1668393995698](https://local.wuanwanghao.top:9000/test/test/image-1668393995698.png)
- 4、CPU和内存按实际情况设置即可删除硬盘删除SATA控制器点击“下一页”
![image-1668394055610](https://local.wuanwanghao.top:9000/test/test/image-1668394055610.png)
- 5、配置列表点击“完成”即可
![image-1668394170762](https://local.wuanwanghao.top:9000/test/test/image-1668394170762.png)
#### 三、IMG转换VMDK磁盘
- 1、打开StarWindConverter默认Local file Next
![image-1668394528151](https://local.wuanwanghao.top:9000/test/test/image-1668394528151.png)
- 2、选择iStore_OS 的 img固件 点击Next
![image-1668394591914](https://local.wuanwanghao.top:9000/test/test/image-1668394591914.png)
- 3、选择 VMware ESX server image 点击Next
![image-1668394666511](https://local.wuanwanghao.top:9000/test/test/image-1668394666511.png)
- 4、生成 VMDK 名字要和虚拟机名称一致 点击Next
![image-1668394754586](https://local.wuanwanghao.top:9000/test/test/image-1668394754586.png)
#### 四 、上传vmdk ,并启动iStore OS
- 1、sftp上传或者数据文件浏览器上传 istoreos.vmdk ,再上传 istoreos -flat.vmdk
![image-1668394919596](https://local.wuanwanghao.top:9000/test/test/image-1668394919596.png)
#### 五、启动虚拟机修改ip 访问
- 1、启动虚拟机 修改ip查看官方文档 修改成exsi绑定网卡同段以便访问,参照pve虚拟机配置ip即可 [地址](http://doc.linkease.com/zh/guide/istoreos/install_pve.html#pve-%E5%AE%89%E8%A3%85)
![image-1668395096359](https://local.wuanwanghao.top:9000/test/test/image-1668395096359.png)
- 2、访问 默认密码password
![image-1668395483119](https://local.wuanwanghao.top:9000/test/test/image-1668395483119.png)

@ -0,0 +1,23 @@
---
icon: edit
date: 2023-02-19
category:
- 系统配置
- Java
headerDepth: 5
---
# java -jar 开启Debug 端口 idea 远程调试
命令
``` shell
java -jar -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 [jar文件名]
```
idea 远程调试
项目添加配置
![image-1676813267156](https://local.wuanwanghao.top:9000/test/test/image-1676813267156.png)
添加 Remote JVM Debug 配置
![image-1676813353259](https://local.wuanwanghao.top:9000/test/test/image-1676813353259.png)
指定项目地址 和端口 就可以愉快的远程调试了
![image-1676813399674](https://local.wuanwanghao.top:9000/test/test/image-1676813399674.png)

@ -0,0 +1,65 @@
---
icon: edit
date: 2023-04-17
category:
- Java
headerDepth: 5
---
# java 使用 ldap 例子
```java
import java.util.Hashtable;
import javax.naming.AuthenticationException;
import javax.naming.CommunicationException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
public class AdTest {
public AdTest() {
}
public static int connect(String host, String post, String username, String password) {
DirContext ctx = null;
int rs = 0;
String domain = "@example.com"; //ldap 服务器域控
String name = username.indexOf(domain) > 0 ? username : username + domain;
Hashtable<String, String> HashEnv = new Hashtable();
HashEnv.put("java.naming.security.authentication", "simple");
HashEnv.put("java.naming.security.principal", name);
HashEnv.put("java.naming.security.credentials", password);
HashEnv.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
HashEnv.put("com.sun.jndi.ldap.connect.timeout", "3000");
HashEnv.put("java.naming.provider.url", "ldap://" + host + ":" + post);
try {
ctx = new InitialDirContext(HashEnv);
System.out.println("身份验证成功!");
} catch (AuthenticationException var22) {
System.out.println("身份验证失败!");
rs = 1;
var22.printStackTrace();
} catch (CommunicationException var23) {
System.out.println("AD域连接失败!");
rs = 2;
var23.printStackTrace();
} catch (Exception var24) {
System.out.println("身份验证未知异常!");
rs = 3;
var24.printStackTrace();
} finally {
if (null != ctx) {
try {
ctx.close();
ctx = null;
} catch (Exception var21) {
var21.printStackTrace();
}
}
}
return rs;
}
}
```

@ -0,0 +1,127 @@
---
icon: edit
date: 2023-02-17
category:
- Java
headerDepth: 5
---
# java 动态执行代码,可以从数据库·拉代码执行的方式例子
```DynamicJavaCompilerUtil.java```
```java
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.stream.Collectors;
public class DynamicJavaCompilerUtil {
static String tmpPath = "./tmp";
public static void Test() throws IOException {
String code = new String("public class T4{ " +
"static void print(String a){ " +
"System.out.println(\"Hello world! \"+ a);" +
"}" +
"static void print(){ " +
"System.out.println(\"Hello world! \");" +
"}" +
"static void print(Integer a,String b){ " +
"System.out.println(\"Hello world! \"+a+b);" +
"}" +
"}");
CompilerToRun(code, "T4", "print", 1, " 2");
}
/*
* @param Code 代码字符串
* @param ClassName 类名
* @param MethodName 需要执行的方法名
* @param MethodParam 需要执行的方法的参数
*/
public static void CompilerToRun(String Code, String ClassName, String MethodName, Object... MethodParam) throws IOException {
isDirExists(new File(tmpPath));
File file = new File(tmpPath + "/" + ClassName + ".java");
RandomAccessFile accessFile = null;
try {
accessFile = new RandomAccessFile(file, "rw");
accessFile.write(Code.getBytes());
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); //调用动态编译的工具
int result = compiler.run(null, null, null, tmpPath + "/" + ClassName + ".java"); //进行动态编译,并返回结果
if (result != 0) {
throw new RuntimeException("编译失败");
}
//通过反射方法动态执行
//1、首先构建文件的目录url地址
URL[] urls = new URL[]{new URL("file:" + tmpPath + "/")};
//2、使用URLClassLoader对象的loadClass方法加载对应类
URLClassLoader loder = new URLClassLoader(urls);
//3、获取所加载类的方法
Class clazz = loder.loadClass(ClassName);
Class[] MethodParamClass = Arrays.asList(MethodParam).stream().map(Object::getClass).collect(Collectors.toList()).toArray(new Class[]{});
// 4、传入方法所需的参数通过invoke运行方法
Method method = clazz.getDeclaredMethod(MethodName, MethodParamClass);
method.setAccessible(true);
method.invoke(null, MethodParam); //当类型为String[]时,需要(Object)new String[] {}初始化
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} finally {
accessFile.close();
deleteFile(new File(tmpPath));
}
}
private static void isDirExists(File file) {
if (!file.exists()) {
file.mkdir();
}
}
private static Boolean deleteFile(File file) {
//判断文件不为null或文件目录存在
if (file == null || !file.exists()) {
System.out.println("文件删除失败,请检查文件是否存在以及文件路径是否正确");
return false;
}
//获取目录下子文件
File[] files = file.listFiles();
//遍历该目录下的文件对象
for (File f : files) {
//判断子目录是否存在子目录,如果是文件则删除
if (f.isDirectory()) {
//递归删除目录下的文件
deleteFile(f);
} else {
//文件删除
f.delete();
//打印文件名
System.out.println("文件名:" + f.getName());
}
}
//文件夹删除
file.delete();
System.out.println("目录名:" + file.getName());
return true;
}
}
```

@ -0,0 +1,15 @@
---
icon: edit
date: 2023-02-19
category:
- 系统配置
- Java
headerDepth: 5
---
# java 编译打包过程中 找不到 tools.jar 的问题,终结解决
> jdk 1.8 中有个tools.jar里面提供了很多便于开发的工具但是由于其是在sun 工作接管Java是开发的不受到甲骨文公司的欢迎在后续的版本中已经移除了tools.jar 所以之后的Java配置环境变量的时候已经不再配置CLASSPATH 了
> 但是有时候在开发中用到tools.jar 的时候,发现在编译过程中 javac 命令是不会去读取CLASSPATH 的jar 去编译的, 网上有好多解决方法放到jre 的lib 里面但是问题无法解决的
> 因为是sun 公司开发的oracle 在引用的这些jar的时候是当作扩展去加载的
只要把tools.jar 放入 jre目录lib 下的ext 扩展类目录就可以在Javac 编译是加载读取

@ -0,0 +1,15 @@
---
icon: edit
date: 2022-10-01
category:
- Kubernetes
headerDepth: 5
---
# k8s 命令行命令
# 删除
强制删除pod
```
kubectl delete pod <podName> -n <namespace> --force --grace-period=0
```

@ -0,0 +1,49 @@
---
icon: edit
date: 2023-03-02
category:
- Kubernetes
headerDepth: 5
---
# kubernetes 挂载单个文件的方式 configMap 及挂载注意事项
**问题现象**
默认挂载 configMap 时kubernetes 会覆盖掉挂载的整个目录,哪怕使用 items 也会导致整个目录被覆盖,那么如何实现挂在单个文件而不覆盖整个目录呢。下面说一下 kubernetes 中如何挂载单个文件而不是整个目录。
**解决方案**
使用 subPath
实际上 kubernets 本身提供了 volumeMounts.subPath 属性用于挂在单个文件而不是整个目录。
下面是一个示例:
```
apiVersion: v1
kind: Pod
metadata:
name: my-lamp-site
spec:
containers:
- name: php
image: php:7.0-apache
volumeMounts:
- mountPath: /var/www/html/index.php
name: index
subPath: index.php
volumes:
- name: index
configMap:
name: php-index
items:
- key: index.php
path: index.php
```
kubesphere
![image-1677744922153](https://local.wuanwanghao.top:9000/test/test/image-1677744922153.png)
注意事项
需要注意的是:
如果使用ConfigMap的subPath挂载为Container的VolumeKubernetes不会做自动热更新
ConfigMap 哪怕不使用subPath的挂载方式 C# 文件修改监听功能也没有触发Golang 的正常,怀疑可能和自己的实现有关.

@ -0,0 +1,144 @@
---
icon: edit
date: 2023-03-09
category:
- 系统配置
headerDepth: 5
---
# kubesphere 部署 zookeeper 和 kafka 以及 在k8s 部署是需要注意的问题
## 搭建zookeeper
选用镜像是官方镜像 zookeeper 内存和cpu 限制不用给太多
![image-1678374469184](https://local.wuanwanghao.top:9000/test/test/image-1678374469184.png)
创建配置字典 和存储卷 用于持久化数据 和挂载配置文件
存储卷 自行创建
配置字典
![image-1678374651276](https://local.wuanwanghao.top:9000/test/test/image-1678374651276.png)
```conf
dataDir=/data # 保存zookeeper中的数据
clientPort=2181 # 客户端连接端口,通常不做修改
dataLogDir=/datalog
tickTime=2000 # 通信心跳时间
initLimit=5 # LF(leader - follower)初始通信时限
syncLimit=2 # LF 同步通信时限
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
maxClientCnxns=60
standaloneEnabled=true
admin.enableServer=true
server.1=localhost:2888:3888;2181
```
deployment.yml
```yml
kind: StatefulSet
apiVersion: apps/v1
metadata:
name: zookeeper
namespace: wanghao
labels:
app: zookeeper
annotations:
kubesphere.io/creator: admin
spec:
replicas: 1
selector:
matchLabels:
app: zookeeper
template:
metadata:
creationTimestamp: null
labels:
app: zookeeper
annotations:
kubesphere.io/restartedAt: '2023-03-08T01:47:35.415Z'
logging.kubesphere.io/logsidecar-config: '{}'
spec:
volumes:
- name: host-time
hostPath:
path: /etc/localtime
type: ''
- name: volume-nffzxk
configMap:
name: zookeeper
defaultMode: 420
- name: volume-2lak5i
persistentVolumeClaim:
claimName: zookeeper
containers:
- name: container-oryqbp
image: zookeeper
ports:
- name: tcp-2181
containerPort: 2181
protocol: TCP
- name: tcp-2888
containerPort: 2888
protocol: TCP
- name: tcp-3888
containerPort: 3888
protocol: TCP
- name: tcp-8080
containerPort: 8080
protocol: TCP
resources:
limits:
cpu: 500m
memory: 200Mi
volumeMounts:
- name: host-time
readOnly: true
mountPath: /etc/localtime
- name: volume-nffzxk
readOnly: true
mountPath: /conf/zoo.cfg
subPath: zoo.cfg
- name: volume-2lak5i
mountPath: /data
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
nodeSelector:
kubernetes.io/hostname: k8s-node3
serviceAccountName: default
serviceAccount: default
securityContext: {}
schedulerName: default-scheduler
serviceName: zookeeper-f6d8
podManagementPolicy: OrderedReady
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
revisionHistoryLimit: 10
```
## 搭建kafka
选用镜像 ```wurstmeister/zookeeper```
![image-1678375058969](https://local.wuanwanghao.top:9000/test/test/image-1678375058969.png)
启动是添加环境变量
```
KAFKA_BROKER_ID0 #该ID是集群的唯一标识
KAFKA_ADVERTISED_LISTENERSPLAINTEXT://local.wuanwanghao.top:9092 #kafka发布到zookeeper供客户端使用的服务地址。
KAFKA_ZOOKEEPER_CONNECT zookeeper.wanghao:2181 #zk的连接地址
KAFKA_LISTENERSPLAINTEXT://0.0.0.0:9092 #允许使用PLAINTEXT侦听器
```
主要一点创建kafka 相应服务的时候一定不要把服务名称定义为```kafka```,
相关问题以踩坑 [Invalid value tcp://10.0.35.234:9092 for configuration port: Not a number of type INT](https://github.com/wurstmeister/kafka-docker/issues/122)

@ -0,0 +1,83 @@
---
icon: edit
date: 2023-04-10
category:
- Linux
tag:
- git
- gitea
headerDepth: 5
---
# linux gitea 搭建
[官方文档](https://docs.gitea.io/zh-cn/)
### 下载可执行文件
```shell
mkdir -p /wanghao/gitea
cd /wanghao/gitea
wget -O gitea https://dl.gitea.com/gitea/1.19.0/gitea-1.19.0-linux-amd64
chmod +x gitea
```
### 验证文件(选作)
Gitea 对打包的二进制文件使用 GPG密钥 签名以防止篡改。 请根据对应文件名 .asc 中包含的校验码检验文件的一致性。
```shell
gpg --keyserver keys.openpgp.org --recv 7C9E68152594688862D62AF62D9AE806EC1592E2
gpg --verify gitea-1.19.0-linux-amd64.asc gitea-1.19.0-linux-amd64
```
校验正确时的信息为 Good signature from "Teabot <teabot@gitea.io>"。 校验错误时的信息为 This key is not certified with a trusted signature!。
### 添加环境变量
>```GITEA_WORK_DIR```:工作目录的绝对路径
```GITEA_CUSTOM```:默认情况下 Gitea 使用默认目录 ```GITEA_WORK_DIR/custom```,您可以使用这个参数来配置 custom 目录
修改环境配置文件
```shell
vim etc/profile
```
追加
```shell
export GITEA_HOME=/wanghao/gitea
export GITEA_WORK_DIR=$GITEA_HOME/workdir
export GITEA_CUSTOM=$GITEA_WORK_DIR/custom
export PATH=$GITEA_HOME:$PATH
```
### 添加systemd 服务
```
sudo vim /etc/systemd/system/gitea.service
```
追加
```ini
[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target
After=network.target
[Service]
RestartSec=2s
Type=simple
User=wanghao
Group=wanghao
WorkingDirectory=/wanghao/gitea/workdir
ExecStart=/wanghao/gitea/gitea web --config /wanghao/gitea/app.ini
Restart=always
Environment=USER=wanghao HOME=/home/wanghao GITEA_WORK_DIR=/wanghao/gitea/workdir
[Install]
WantedBy=multi-user.target
```
启动
```
systemctl enable gitea
systemctl start gitea
```
### 开放端口
```shell
firewall-cmd --zone=public --add-port=3000/tcp --permanent
```
### 问题解决
ssh clone 时遇到[No supported authentication methods available (server sent: publickey) ](https://blog.csdn.net/qq_37726813/article/details/127475348)

@ -0,0 +1,68 @@
---
icon: edit
date: 2023-04-11
category:
- Linux
tag:
- harbor
headerDepth: 5
---
# linux harbor 搭建, 以及nginx ssl 代理
### 前置
首先确保机器以及安装好 docker 以及 docker-compose
>[Linux 安装 Docker](https://local.wuanwanghao.top:30549/archives/linux%E5%AE%89%E8%A3%85docker)
>[Linux 安装 docker-compose](https://local.wuanwanghao.top:30549/archives/linux%E5%AE%89%E8%A3%85docker-compose)
### 下载离线安装包
[github_harbor_releases](https://github.com/goharbor/harbor/releases)
创建工作目录 下载安装包并解压
```shell
mkdir -p /wanghao/docker
cd /wanghao/docker
wget https://ghproxy.com/https://github.com/goharbor/harbor/releases/download/v2.5.6/harbor-offline-installer-v2.5.6.tgz
tar -xvf harbor-offline-installer-v2.5.6.tgz
```
### 修改配置文件
进入解压目录 /wanghao/docker/harbor ,拷贝模版创建配置文件
```shell
cd /wanghao/docker/harbor
cp harbor.yml.tmpl harbor.yml
```
修改harbor.yml 以下的配置项
```
hostname: 访问的域名
http:
port: 5500
external_url: https://域名:端口
harbor_admin_password: 管理员密码
```
### 启动harbor
```
./install.sh
```
### 配置nginx 代理 ssl
```
server {
listen 443 ssl;
server_name 域名 ;#修改为自己的域名
ssl_certificate ; #域名证书
ssl_certificate_key ; #域名证书
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://localhost:5500;
client_max_body_size 0;
proxy_connect_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 6 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
```

@ -0,0 +1,46 @@
---
icon: edit
date: 2023-04-04
category:
- 系统配置
- Linux
headerDepth: 5
---
# linux 制作简单systemctl 的service
在系统路径```/usr/lib/systemd/system/``` 下创建 ```服务名```.service 文件
下面frp.service模板
```toml
[Unit]
#描述
Description=MainFrpService
#在网络启动后执行Frp服务
After=network.target
[Service]
Type=simple
#以root权限运行
User=root
#停止时重启
Restart=on-abort
#启动命令
ExecStart=/wanghao/frps/frp_0.44.0_linux_amd64/frps -c /wanghao/frps/frp_0.44.0_linux_amd64/frps.ini
[Install]
WantedBy=multi-user.target
```
创建好后就可以使用systemctl 命令来操作服务
```shell
#启动服务
ststemctl start frp
#重启服务
systemctl restart frp
#查看服务状态
systemctl status frp
#开启开机自启动
systemctl enable frp
```

@ -0,0 +1,23 @@
---
icon: edit
date: 2023-03-12
category:
- 系统配置
headerDepth: 5
---
# linux 发布重启项目简单脚本命令
``` shell
cd $project_path
ps -ef | grep $bin_file | grep -v grep| awk '{print $2}' | xargs kill -9
nohup java -jar $project_path/$bin_file >catalina.out 2>&1 &
```
**$project_path 替换为可执行文件的路径**
**$bin_file 替换为可执行文件的名称**
```cd $project_path``` 进入可执行文件目录
```ps -ef | grep $bin_file | grep -v grep| awk '{print $2}' | xargs kill -9``` 获取可执行文件的pid 进程id 然后结束该进程id
```nohup java -jar $project_path/$bin_file >catalina.out 2>&1 & ``` 执行可执行文件并输出日志到指定文件

@ -0,0 +1,26 @@
---
icon: edit
date: 2023-04-10
category:
- Linux
tag:
- alias
headerDepth: 5
---
# linux 命令别名 alias关于ls命令列出目录没有颜色的解决方案
一版来说安装ArchLinux 系统 使用 ls 命令列出目录是没有颜色的。
这是因为没有使用命令别名的原因。
实际上当我们使用 ```ls --color=auto``` 命令时是有颜色的
```shell
ls --color=auto
```
这是因为 ArchLinux 发行版高度自由所以很多的配置都没有给我做所以像其他的发行版linux 系统都是有做命令别名的
所以在这里我们打开 环境配置文件 ```~/.bashrc``` 追加配置
```shell
alias ls='ls --color=auto'
```
>这里注意有一点 ```alias ls=``` 后面 不要带空格,直接紧挨着'ls --color=auto' ,不然也会把空格也当作成命令的一部分,无法识别

@ -0,0 +1,11 @@
---
icon: edit
date: 2023-04-09
category:
- Linux
headerDepth: 5
---
# linux 命令大全
[ Linux命令大全 ](https://linux265.com/course/linux-commands.html)

@ -0,0 +1,29 @@
---
icon: edit
date: 2023-03-15
category:
- 系统配置
- Linux
headerDepth: 5
---
# linux 查看磁盘使用情况,查看文件夹及文件大小命令
##### ```df -h``` 查看磁盘使用情况
```shell
df -h
```
![image-1678871170294](https://local.wuanwanghao.top:9000/test/test/image-1678871170294.png)
##### ```du -h --max-depth=1``` 列出当前文件夹下 深度为 1 的文件夹大小
```shell
du -h --max-depth=1
```
![image-1678871267580](https://local.wuanwanghao.top:9000/test/test/image-1678871267580.png)
max-depth=1表示几级子目录如果不需要子目录=0 ,即可
##### ```du -h “文件名”``` 列出当前文件的大小
```shell
du -h “文件名”
```
![image-1678871356607](https://local.wuanwanghao.top:9000/test/test/image-1678871356607.png)

@ -0,0 +1,119 @@
---
icon: edit
date: 2023-04-09
category:
- Linux
headerDepth: 5
---
# linux 磁盘使用分区工具 fdisk, 从新磁盘分区到挂载的全过程
### fdisk
fdisk命令的英文全称是“Partition table manipulator for Linux”即作为磁盘的分区工具。进行硬盘分区从实质上说就是对硬盘的一种格式化 用一个形象的比喻,分区就好比在一张白纸上画一个大方框,而格式化好比在方框里打上格子。
| 参数 | 详情 |
| ---- | -------------------------------------------------------------------- |
| -b | 指定每个分区的大小 |
| -l | 列出指定的外围设备的分区表状况 |
| -s | 将指定的分区大小输出到标准输出上,单位为区块 |
| -u | 搭配”-l”参数列表会用分区数目取代柱面数目来表示每个分区的起始地址 |
| -v | 显示版本信息 |
| ... | ... |
### 查看磁盘信息
首先使用 fdisk -l 查看系统挂载磁盘设备信息
一般sata 磁盘设备 名称 是```/dev/sda``` 或者``` /dev/sdb```
找到你新添加磁盘设备
### 开始分区
假设你新添加磁盘设备 设备名称为/dev/sdb
```shell
fdisk /dev/sdb
```
然后输入m 打开详细详细
```
欢迎使用 fdisk (util-linux 2.23.2)。
更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。
命令(输入 m 获取帮助)m
命令操作
a toggle a bootable flag
b edit bsd disklabel
c toggle the dos compatibility flag
d delete a partition
g create a new empty GPT partition table
G create an IRIX (SGI) partition table
l list known partition types
m print this menu
n add a new partition
o create a new empty DOS partition table
p print the partition table
q quit without saving changes
s create a new empty Sun disklabel
t change a partition's system id
u change display/entry units
v verify the partition table
w write table to disk and exit
x extra functionality (experts only)
```
### 创建分区,指定分区大小
1.然后输入 n 创建新的分区 磁盘默认可以创建的分区为4个
2.根据提示输入要创建的分区号 1....4
3.默认为1 直接回车 或者 输入1 即可
4.输入分区大小,默认为磁盘容量最多值 ,可以输入+1G .... 指定容量为1G 也可以自定义指定大小 ```+?G``` ?号代表 容量大小 。 确定好直接回车
5.输入w 保存分区设置并退出
### 格式化分区文件系统
>上一步保存好分区设置后可以使用 fdisk -l 查看分区信息 ,如果没有可以使用 ```partprobe 磁盘设备名称``` 命令 来通知内核系统,请求操作系统重新加载分区表。
```shell
partprobe /dev/sdb
```
一般来说centos 系统的文件系统类型为 xfs 和 ext4 这里使用xfs 进行格式化
```shell
mkfs.xfs /dev/sdb1
```
### 挂载分区
1.这里默认创建的分区为 ```/dev/sdb1``` 使用mount 命令挂载分区到指定目录
>这里有一点要注意,如果要挂载的目录里面有数据,需要备份到其他目录里面,等挂载完成后重新移动过来 这里假设挂载的目录为 /wanghao, 我们重命名文件夹 然后再次创建文件夹 来挂载
```shell
mv /wanghao /wanghao/bak
mkdir /wanghao
mount /dev/sdb1 /wanghao
cp -r /wanghao_bak/* /wanghao/
rm -rf /wanghao_bak
```
当然如果挂载的空目录上可以直接挂载 假设/wanghao 是空目录
```shell
mount /dev/sdb1 /wanghao
```
### 取消挂载命令为 umount 如果有问题可以取消挂载
```shell
umount /wanghao
```
### mount 是临时挂载命令 这里进行持久化挂载,
vim /etc/fstab 命令,编辑 fstab 文件,在最后一行添加一条记录,如 /dev/sdb1 /wanghao xfs defaults 0 0 ,保存并退出
```
vim /etc/fstab
#输入i 进入编辑模式 ,找到空行进行输入
/dev/sdb1 /wanghao xfs defaults 0 0
#输入完毕后 按ESC键 ,然后输入 :wq 即可保存并退出
```
### lsblk
查看当前系统挂载的硬盘信息 并列出所有的硬盘设备
### partprobe 命令
partprobe命令用于重读分区表将磁盘分区表变化信息通知内核请求操作系统重新加载分区表。如果删除文件后仍然提示占用空间可以用partprobe在不重启的情况下重读分区 。
|参数 |详情|
|-------|-------|
|-d |不更新内核|
|-s |显示摘要和分区|
|-h |显示帮助信息|
|-v |显示版本信息|
### 文件系统
> Linux 的文件系统取决于它的发行版。一般来说,基于 Red Hat 的发行版(如 CentOS、Fedora、RHEL 等)使用 xfs 或 ext4 文件系统,基于 Debian 的发行版(如 Ubuntu、Mint、Debian 等)使用 ext4 文件系统,基于 Arch Linux 的发行版(如 Manjaro、Arch Linux 等)使用 ext4 或 btrfs 文件系统.

@ -0,0 +1,37 @@
---
icon: edit
date: 2022-11-02
category:
- Linux
tag:
- 网络
headerDepth: 5
---
# linux 通过SpeedTest工具网络测速
### 下载工具
```shell
wget -O speedtest-cli https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py
```
### 赋予执行权限
```shell
chmod +x speedtest-cli
```
### 执行
```shell
./speedtest-cli --share
```
![image](https://local.wuanwanghao.top:9000/test/test/image.png)
### 查看所有国内测试节点
```shell
./speedtest-cli --list | grep China
```
![image-1667377461538](https://local.wuanwanghao.top:9000/test/test/image-1667377461538.png)
### 指定测试节点测试
```shell
./speedtest-cli --server=41910 --share
```
![image-1667377603338](https://local.wuanwanghao.top:9000/test/test/image-1667377603338.png)

@ -0,0 +1,119 @@
---
icon: edit
date: 2023-03-06
category:
- 系统配置
headerDepth: 5
---
# mongodb及使用
## 一、mongoDB是什么
MongoDB是一个NoSQL的非关系型数据库 ,支持海量数据存储,高性能的读写。
### 1. mongo的体系结构
![image-1678084882505](https://local.wuanwanghao.top:9000/test/test/image-1678084882505.png)
mongo中的集合相当于mysql中表的概念
mongo中的文档相当于mysql中行的概念
mongo中的域相当于mysql中字段/列的概念;
### 2. mongoDB的特点(或使用场景)
支持存储海量数据;(例如:直播中的打赏数据)
支持频繁的数据读写;(例如:游戏道具);
数据安全性不高,存在数据误差(丢失数据)
mongoDB不支持多表操作不支持事务
mongoDB使用Bson存储格式支持动态字段管理
### 3. mongoDB与mysql、redis对比
与redis对比
1. redis纯内存数据库内存不足时触发淘汰策略mongoDB使用内存加磁盘的存储策略具有高扩展性
2. mongoDB使用Bson存储格式支持动态字段管理方便扩展
与mysql对比
1. mongoDB不支持多表操作不支持事务
2. mongoDB使用Bson存储格式支持动态字段管理
查询效率对比
Redis > MongoDB > MySQL
### 4. mongoDB存储原理
![image-1678084900902](https://local.wuanwanghao.top:9000/test/test/image-1678084900902.png)
mongoDb采用内存加磁盘的方式存储数据
mongoDb支持数据分片当单一的服务器中磁盘不够用的时候还可以串联其他服务器
客户端的请求到达内存时,先在日志中记录下操作记录,然后再去操作内存;
内存中的日志每10ms向磁盘中的日志进行同步一次数据则每分钟同步一次
客户端先去内存中查询数据,内存中没有再去查询磁盘;
当客户端写入的时候,会先写入到内存中,内存中写入后请求直接返回,内存中的数据会根据同步策略同步到磁盘;
如果机器宕机在重启服务的时候会解析磁盘中的日志和磁盘中的数据进行对比将未入到磁盘中的数据写入磁盘但可能会丢失10ms的数据
## 二、使用docker安装mongo
### 1.安装
1.拉取mongo镜像
``` shell
docker pull mongo:4.4
```
2.创建mongo数据持久化目录
``` shell
mkdir -p /docker_volume/mongodb/data
```
3.运行容器
``` shell
docker run -d --name mongo -v /docker_volume/mongodb/data:/data/db -p 27017:27017 mongo:4.4 --auth --bind_ip 0.0.0.0
```
auth需要密码才能访问容器服务
--bind_ip 0.0.0.0 监听从所有ip请求来的流量
相关命令行参数 请参照官方文档 [mongod](https://www.mongodb.com/docs/manual/reference/program/mongod/#cmdoption-mongod-auth)
### 2.创建用户
登录mongo容器并进入到【admin】数据库
```
docker exec -it mongo mongo admin
```
创建一个用户mongo 默认没有用户
db.createUser({ user:'root',pwd:'123456',roles:[ { role:'userAdminAnyDatabase', db: 'admin'},'readWriteAnyDatabase']});
```【user:root设置用户名为root```
```【pwd:123456设置密码为123456```
```【role:userAdminAnyDatabase只在admin数据库中可用赋予用户所有数据库的userAdmin权限```
```【db: admin可操作的数据库```
```【readWriteAnyDatabase赋予用户读写权限 ```
dbAdmin允许用户在指定数据库中执行管理函数如索引创建、删除查看统计或访问system.profile
### 3. 连接、测试
连接mongo数据库
```shell
db.auth('root', '123456')
```
测试数据库 创建集合
```shell
db.createCollection("user")
```
测试数据库,插入一条语句
```shell
db.user.insert({"name":"zhangsan","age":18})
```
测试数据库,查询刚才插入的语句
```shell
db.user.find()
```
### 4.修改密码
#### 1、首先通过以下命令登录mongodb数据库。
show dbs 查看数据库
use dbname 进入数据库
show users 查看当前数据库用户权限据。
#### 2、使用以下方法修改密码即可。
方法1
```shell
db.changeUserPassword("usertest","changepass");
```
方法2
```shell
db.updateUser("usertest",{pwd:"changepass1"})
```

@ -0,0 +1,33 @@
---
icon: edit
date: 2022-06-20
category:
- 系统配置
headerDepth: 5
---
# mysql 被黑客攻击了 惨痛教训
**今天鼓捣c++ 项目的时候 需要用下nacos 准备docker 安装个发现数据库被黑客攻击了太惨了,还好数据没丢只是 把我的root 权限给改了。
自己的mysql 密码太简单了,以后要把密码复杂化**
下面解决方法
先用本地用户登录mysql
赋予远程账号全部权限;
刷新配置;
修改远程账号密码
刷新配置;
```
mysql> grant all on *.* to root@'%';
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> ALTER USER 'root'@'%' IDENTIFIED BY 'xxxxxx';
Query OK, 0 rows affected (0.01 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
```

@ -0,0 +1,79 @@
---
icon: edit
date: 2022-11-04
category:
- 系统配置
- Linux
tag:
- nginx
- websocket
headerDepth: 5
---
# nginx 实现websocket 代理
WebSocket是HTML5下一种新的协议。它实现了浏览器与服务器全双工通信能更好的节省服务器资源和带宽并达到实时通讯的目的。它与HTTP一样通过已建立的TCP连接来传输数据但是它和HTTP最大不同是
``` 1 WebSocket是一种双向通信协议。在建立连接后WebSocket服务器端 和客户端都能主动向对方发送或接收数据就像Socket一样```
```2WebSocket需要像TCP一样先建立连接连接成功后才能相互通信。```
WebSocket协议相比较于HTTP协议成功握手后可以多次进行通讯直到连接被关闭。但是WebSocket中的握手和HTTP中的握手兼容 它使用HTTP中的Upgrade协议头将连接从HTTP升级到WebSocket。这使得WebSocket程序可以更容易的使用现已存在的基础设施。大部分现在的浏览器都支持WebSocket。
在实际的生产环境中要求多个WebSocket服务器必须具有高性能和高可用那么WebSocket协议就需要一个负载均衡层Nginx从「1.3」版本开始支持WebSocket其可以作为一个反向代理和为WebSocket程序做负载均衡。
WebSocket协议与HTTP协议不同但WebSocket握手与HTTP兼容使用HTTP升级工具将连接从HTTP升级到WebSocket。这允许WebSocket应用程序更容易地适应现有的基础架构。例如WebSocket应用程序可以使用标准HTTP端口80和443从而允许使用现有的防火墙规则。
「WebSocket应用程序可以在客户端和服务器之间保持长时间运行的连接」从而有助于开发实时应用程序。用于将连接从HTTP升级到WebSocket的HTTP升级机制使用Upgrade和Connection头。反向代理服务器在支持WebSocket时面临一些挑战。一个是WebSocket是一个逐跳协议因此当代理服务器拦截客户端的升级请求时需要向后端服务器发送自己的升级请求包括相应的头文件。此外由于WebSocket连接长期存在与HTTP使用的典型短期连接相反反向代理需要允许这些连接保持打开状态而不是关闭它们因为它们似乎处于空闲状态。
允许在客户机和后端服务器之间建立隧道Nginx支持WebSocket。对于NGINX将升级请求从客户端发送到后台服务器必须明确设置Upgrade和Connection标题。
-----------------------------------
### Nginx开启WebSocket代理的配置方法如下
#### 编辑nginx.conf在http区域内一定要添加下面配置
```conf
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
```
「解释一下map指令的作用该作用主要是根据客户端请求中的值来构造改变connection_upgrade的值即根据变量的值创建新的变量connection_upgrade 创建的规则就是{}里面的东西。其中的规则没有做匹配,因此使用默认的,即 http_upgrade为空字符串的话那么值就是 close。
#### 在location匹配配置中添加如下内容
```conf
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "$connection_upgrade";
```
#### 一次完整的实例
```
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 30880 ssl;
#填写绑定证书的域名
server_name local.wuanwanghao.top;
#证书文件名称
ssl_certificate /etc/nginx/ssl/local.wuanwanghao.top_bundle.crt;
#私钥文件名称
ssl_certificate_key /etc/nginx/ssl/local.wuanwanghao.top.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
error_page 497 307 =301 @back;
location @back {
rewrite ^(.*)$ https://$host:$server_port$1 permanent;
}
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
#网站主页路径。此路径仅供参考,具体请您按照实际目录操作。
proxy_pass http://192.168.3.140:30880;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "$connection_upgrade";
}
}
```

@ -0,0 +1,92 @@
---
icon: edit
date: 2022-12-26
category:
- nodejs
tag:
- mqtt
headerDepth: 5
---
# nodejs 运行 mqtt
npm 安装 mqtt
```shell
npm install -g mqtt
```
客户端
```js
var mqtt = require('mqtt');
//var process = require('process');
var client = mqtt.connect('mqtt://192.168.3.254:1883', {
username: "admin",
password: "public",
clientId: 'client9'
});
function getYYYYMMDDhhmmssByDate() {
let date = new Date();
let value = date.getFullYear() * 10000000000 +
(date.getMonth() + 1) * 100000000 +
date.getDate() * 1000000 +
date.getHours() * 10000 +
date.getMinutes() * 100 +
date.getSeconds();
return value;
};
client.on('connect', function() {
console.log("connect success");
client.subscribe('/server/task/roleId/1/update_task_data');
client.subscribe('/server/task/roleId/1/setValue');
});
client.on('message', function(topic, message, packet) {
console.log(" ");
console.log(process.env.JAVA_HOME);
console.log("time: ", getYYYYMMDDhhmmssByDate());
var jsonStr = message.toString()
console.log("jsonStr: " + jsonStr);
console.log(" ");
});
```
服务端
```js
var mqtt = require('mqtt');
var client = mqtt.connect('mqtt://192.168.3.254:1883', {
username: 'admin',
password: 'public',
clientId: 'server1'
});
function getJsonStr() {
return JSON.stringify({
"event": "update_task_data",
"data": {
"arrTaskId": [],
"arrTaskInst": [{
"id": 1,
"roleId": 1,
"moduleId": "0",
"userId": 0,
"taskId": 9999,
"finish": 0,
"taskNodeId": 15,
"taskNodeStatus": 0,
"taskNodeStartTime": 20210811,
"beforeNodeId": 14
}]
},
"open": (Math.round(Math.random())+1)*10,
"state": (Math.round(Math.random())+1)*10,
});
}
// 推送的频道和数据
setInterval(() => {
client.publish("/server/task/roleId/1/update_task_data", getJsonStr(), {qos: 2, retain: false});
}, 5000)
```

@ -0,0 +1,91 @@
---
icon: edit
date: 2022-12-26
category:
- nodejs
tag:
- modbus
headerDepth: 5
---
# nodejs 运行modbus
npm 安装 modbus-serial
```shell
npm install -g modbus-serial
```
modbus 客户端
```js
// create an empty modbus client
var ModbusRTU = require("modbus-serial");
var client = new ModbusRTU();
// open connection to a tcp line
client.connectTCP("127.0.0.1", { port: 8502 });
client.setID(1);
// read the values of 10 registers starting at address 0
// on device number 1. and log the values to the console.
setInterval(function() {
client.readHoldingRegisters(0, 10, function(err, data) {
if(data){
console.log(data.data);
}
});
}, 1000);
```
modbus 服务端
```js
// create an empty modbus client
var ModbusRTU = require("modbus-serial");
var vector = {
getInputRegister: function(addr, unitID) {
// Synchronous handling
return addr;
},
getHoldingRegister: function(addr, unitID, callback) {
// Asynchronous handling (with callback)
setTimeout(function() {
// callback = function(err, value)
callback(null, addr + 7000);
}, 10);
},
getCoil: function(addr, unitID) {
// Asynchronous handling (with Promises, async/await supported)
return new Promise(function(resolve) {
setTimeout(function() {
resolve((addr % 2) === 0);
}, 10);
});
},
setRegister: function(addr, value, unitID) {
// Asynchronous handling supported also here
console.log("set register", addr, value, unitID);
return;
},
setCoil: function(addr, value, unitID) {
// Asynchronous handling supported also here
console.log("set coil", addr, value, unitID);
return;
},
readDeviceIdentification: function(addr) {
return {
0x00: "MyVendorName",
0x01: "MyProductCode",
0x02: "MyMajorMinorRevision",
0x05: "MyModelName",
0x97: "MyExtendedObject1",
0xAB: "MyExtendedObject2"
};
}
};
// set the server to answer for modbus requests
console.log("ModbusTCP listening on modbus://0.0.0.0:8502");
var serverTCP = new ModbusRTU.ServerTCP(vector, { host: "0.0.0.0", port: 8502, debug: true, unitID: 1 });
serverTCP.on("socketError", function(err){
// Handle socket error if needed, can be ignored
console.error(err);
});
```

@ -0,0 +1,79 @@
---
icon: edit
date: 2022-12-26
category:
- python
tag:
- opcua
headerDepth: 5
---
# python 运行 opcua
pip 安装 opcua
``` shell
pip install opcua
```
opcua 客户端
```python
from opcua import Client
if __name__ == "__main__":
client = Client("opc.tcp://localhost:4840/freeopcua/server/")
# client = Client("opc.tcp://admin@localhost:4840/freeopcua/server/") #connect using a user
try:
client.connect()
# Client has a few methods to get proxy to UA nodes that should always be in address space such as Root or Objects
root = client.get_root_node()
print("Objects node is: ", root)
# Node objects have methods to read and write node attributes as well as browse or populate address space
print("Children of root are: ", root.get_children())
# get a specific node knowing its node id
#var = client.get_node(ua.NodeId(1002, 2))
#var = client.get_node("ns=3;i=2002")
#print(var)
#var.get_data_value() # get value of node as a DataValue object
#var.get_value() # get value of node as a python builtin
#var.set_value(ua.Variant([23], ua.VariantType.Int64)) #set node value using explicit data type
#var.set_value(3.9) # set node value using implicit data type
# Now getting a variable node using its browse path
myvar = root.get_child(["0:Objects", "2:MyObject", "2:MyVariable"])
obj = root.get_child(["0:Objects", "2:MyObject"])
print("myvar is: ", myvar)
print("myobj is: ", obj)
# Stacked myvar access
# print("myvar is: ", root.get_children()[0].get_children()[1].get_variables()[0].get_value())
finally:
client.disconnect()
```
opcua 服务端
```python
import sys
sys.path.insert(0, "..")
import time
from opcua import ua, Server
if __name__ == "__main__":
# setup our server
server = Server()
server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
# setup our own namespace, not really necessary but should as spec
uri = "http://examples.freeopcua.github.io"
idx = server.register_namespace(uri)
# get Objects node, this is where we should put our nodes
objects = server.get_objects_node()
print(objects)
# populating our address space
myobj = objects.add_object(idx, "MyObject")
myvar = myobj.add_variable(idx, "MyVariable", 6.7)
myvar.set_writable() # Set MyVariable to be writable by clients
# starting!
server.start()
try:
count = 0
while True:
time.sleep(1)
count += 0.1
myvar.set_value(count)
finally:
#close connection, remove subcsriptions, etc
server.stop()
```

@ -0,0 +1,80 @@
---
icon: edit
date: 2023-04-06
category:
- Linux
tag:
- rm
- 管道符
- |
- find
- grep
headerDepth: 5
---
# rm 特殊用法,删除文件夹指定格式的文件
rm是我们在Linux下删除文件经常用到的命令但是有时候我们目录下有很多个文件想要删除偏偏却要保留其中1个或几个文件那怎么办呢很多新手朋友可能会采取一个一个文件删除的方法来操作但是如果文件很多呢删到啥时候啊~~
今天我们就来教大家使用rm命令删除文件的时候如何排除指定的文件不删除指定文件。首先我们来看一下平时我们是怎么使用rm命令的。
**1、删除单个文件**
```
rm 1.txt
```
**2、强制删除文件无需确认**
```
rm -rf 1.txt
```
**3、删除文件夹**
```
rm -rf mydir
```
**4、删除目录下全部文件包括文件夹**
```
rm -rf *
```
**5、删除全部文件但保留1.txt**
```
rm -rf !(1.txt)
```
正常情况下是全部文件被删除了只留下了1.txt但是有时候我们的系统没配置好可能会报错例如下面这种
```
root@abc:/home/# rm -rf !(1.txt)
-bash: !: event not found
```
上面这种情况是因为我们的系统没有开启通配符功能,我们执行下面的命令开启通配符功能先:
```
shopt -s extglob
```
查看通配符功能是否开启on表示已经开启
```
shopt -s
```
然后我们再次执行前面的命令就可以看到文件已经全部删除了只保留了1.txt
```
rm -rf !(1.txt)
```
**6、删除全部文件保留1.txt和2.txt**
```
rm -rf !(1.txt|2.txt)
```
上面我们说的都是直接用rm + !(叹号)来排除文件的,下面我们搞个高深一点的,用**find + grep + xargs**三个命令一起用
**7、删除全部文件保留1.txt**
```
find * | grep -v 1.txt | xargs rm
```
这里我们要特别注意grep的-v参数-v参数表示反选比如我们上面指定了-v 1.txt即排除掉1.txt选中其他全部文件。所以这样执行之后1.txt就被排除了
**8、删除全部文件保留1.txt和2.txt**
```
find * | grep -v '\(1.txt\|2.txt\)' | xargs rm
```
**9、删除文件中不包含_字符的文件**
```
find * | grep -v '_' | xargs rm
```
这里要特别留意,括号()跟括号内的竖线|需要添加****进行转义,否则会报错

@ -0,0 +1,80 @@
---
icon: edit
date: 2023-01-16
category:
- 系统配置
- cpp
tag:
- CMake
- vcpkg
- CLion
headerDepth: 5
---
# vcpkg+CLion+cmake+MinGW使用
#### vcpkg介绍
```vcpkg 是用于 C++ 的一种命令行包管理器。 它极大地简化了 Windows、Linux 和 macOS 上第三方库的购置与安装。 如果项目要使用第三方库,建议通过 vcpkg 来安装它们。 vcpkg 同时支持开源和专有库。 已测试 vcpkg Windows 目录中所有库与 Visual Studio 2015、Visual Studio 2017 及 Visual Studio 2019 的兼容性。 在 Windows 和 Linux/macOS 目录之间vcpkg 现已支持超过 1900 个库。 C++ 社区正在不断向两个目录添加更多的库。```
#### 安装
从 GitHub 克隆 vcpkg 存储库https://github.com/Microsoft/vcpkg。 可凭喜好下载到任意文件夹位置。 此位置的根是 vcpkg。 下载完成后,在命令行界面切换到该目录。
``` shell
git clone https://github.com/Microsoft/vcpkg.git
```
在 vcpkg 根目录中,运行 vcpkg 引导程序:
```shell
bootstrap-vcpkg.bat (Windows)
./bootstrap-vcpkg.shLinux、macOS
```
最后根据系统不同,添加到各自得环境变量里面
在 Linux 或 macOS 上,你可能需要在以下示例中使用 ./ 作为 vcpkg 命令的前缀。 请记得从 vcpkg 根目录运行这些命令。
#### 用法
[https://github.com/microsoft/vcpkg/blob/master/README_zh_CN.md](https://github.com/microsoft/vcpkg/blob/master/README_zh_CN.md)
安装 Jsoncpp
这里我们使用 vcpkg 安装 jsoncpp 并指定 vcpkg 的 triplet 为 mingw用户可以通过执行 vcpkg help triplet 来查看 vcpkg 支持的所有 triplet
```shell
vcpkg install jsoncpp:x64-mingw-static
```
![image-1673855329302](https://local.wuanwanghao.top:9000/test/test/image-1673855329302.png)
CMake 使用 jsoncpp
```shell
find_package(jsoncpp CONFIG REQUIRED)
target_link_libraries(main PRIVATE jsoncpp_object jsoncpp_static)
```
就是我们要在我们项目中 CMakeLists.txt 中填入的内容如下所示
```txt
cmake_minimum_required(VERSION 3.22)
set(VCPKG_TARGET_TRIPLET "x64-mingw-static" CACHE STRING "" FORCE)
project(main)
set(CMAKE_CXX_STANDARD 11)
find_package(jsoncpp CONFIG REQUIRED)
add_executable(main main.cpp)
target_link_libraries(main PRIVATE jsoncpp_object jsoncpp_static JsonCpp::JsonCpp)
```
其中的第二行 set(VCPKG_TARGET_TRIPLET "x64-mingw-static" CACHE STRING "" FORCE) 是设置 vcpkg 的 triplet
#### Clion 配置
在 CMake options 中填入
```shell
-DCMAKE_TOOLCHAIN_FILE=<你安装vcpkg的位置>/scripts/buildsystems/vcpkg.cmake
```
![image-1673855528935](https://local.wuanwanghao.top:9000/test/test/image-1673855528935.png)
#### 测试
main.cpp
```cpp
#include <iostream>
#include <json/json.h>
int main() {
Json::Value root;
root["one"] = "one";
std::cout << root.toStyledString() << std::endl;
std::cout << "Hello, World!" << std::endl;
return 10;
}
```
![image-1673855622590](https://local.wuanwanghao.top:9000/test/test/image-1673855622590.png)

@ -0,0 +1,38 @@
---
icon: edit
date: 2022-11-03
category:
- 系统配置
- Linux
tag:
- 网络
- EXSI
- SSL
- 域名
headerDepth: 5
---
# vmware EXSI 修改系统默认SSL证书和密钥
### ssh链接到exsi
![image-1667434778798](https://local.wuanwanghao.top:9000/test/test/image-1667434778798.png)
### 跳转到 ```/etc/vmware/ssl``` 路径下
```shell
cd /etc/vmware/ssl
```
### 将路径下的两个文件备份 修改后辍为bak
![image-1667434900974](https://local.wuanwanghao.top:9000/test/test/image-1667434900974.png)
### 上传自己的ssl 证书 和密钥 名称都修改为 ```rui```
![image-1667435003688](https://local.wuanwanghao.top:9000/test/test/image-1667435003688.png)!
### 使证书生效
```shell
/etc/init.d/hostd restart
/etc/init.d/vpxa restart
```
![image-1667435106747](https://local.wuanwanghao.top:9000/test/test/image-1667435106747.png)

@ -0,0 +1,24 @@
---
icon: edit
date: 2023-03-15
category:
- 系统配置
- Java
headerDepth: 5
---
# vscode 运行Java 项目的时候的编码问题idea运行成功但是vscode运行就nacos 拉取配置中文注释解析失败的问题解决。
最近尝试再用vscode 在跑项目,意外的觉得很好用,简洁。尝试命令行跑项目有种很棒的感觉。但是今天有个新项目在跑的时候却出现了个很头疼的问题。
就是项目运行的的时候要去nacos 拉取配置但是就是解析报错很纳闷就是idea 运行就没有问题。我对比两者运行时候的命令发现idea 在运行期间
jvm 参数多了 -Dfile.encoding=UTF-8 文件编码指定了 UTF-8 🤣,无语了。
以下是在vscode 中启动项目追加 jvm 参数的方式
```json
{
"spring-boot.ls.java.vmargs": [
"-Dfile.encoding=utf-8"
],
"java.debug.settings.vmArgs": "-Dfile.encoding=UTF-8",
}
```

@ -0,0 +1,221 @@
---
icon: edit
date: 2023-04-05
category:
- 系统配置
- windows
tag:
- chocolatey
- pkgManger
- winget
headerDepth: 5
---
# windows 下包管理器
# windows 下包管理器
- chocolatey
- winget
- Scoop
## chocolatey
chocolatey 并非微软官方的包管理器,但却是最受欢迎的包管理器
[chocolatey官网](https://chocolatey.org/)
[官方安装文档](https://docs.chocolatey.org/en-us/choco/setup)
[官方配置文档](https://docs.chocolatey.org/en-us/configuration)
### CMD 安装
```shell
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "[System.Net.ServicePointManager]::SecurityProtocol = 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
```
### powershell安装
```shell
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
```
### 升级
```
choco upgrade chocolatey
```
### 卸载
#### 文件夹
Chocolatey 的大部分内容包含在C:\ProgramData\chocolatey或任何$env:ChocolateyInstall计算结果中。您可以简单地删除该文件夹。
- 笔记
您可以先备份子文件夹libbin以防万一您在删除 Chocolatey 时发现不良结果。请记住,并非每个 Chocolatey 包都是安装程序包,这些子文件夹中可能包含一些未安装的应用程序,这些应用程序可能会丢失。拥有备份将使您能够测试该方面。
#### 环境变量
有一些环境变量需要调整或删除。
- ChocolateyInstall
- ChocolateyToolsLocation
- ChocolateyLastPathUpdate
- PATH (will need updated to remove)
### 使用
使用巧克力
现在你的机器上有 Chocolatey需要安装你可以运行几个命令。
查看命令参考。我们将使用安装命令。
让我们安装Notepad++。
以管理员身份打开命令行。
键入choco install notepadplusplus并按 Enter。
```
choco install notepadplusplus
```
>就是这样。非常简单但功能强大的小概念!
覆盖默认安装目录或其他高级安装概念
是的,我们通过使用安装参数来支持它 - 请参阅安装参数
如果您想将本机参数传递给安装程序,例如安装目录,您需要知道传递给该特定安装程序的静默参数,然后您可以在命令行或 packages.config 中指定它。
>如果它是 MSI那么通常您可以通过-ia "INSTALLDIR=""D:\Program Files"""(对于 cmd.exe对于 PowerShell 则不同)。查看如何传递选项/开关以了解有关传递引用值的细节。
>例如Notepad++ 使用NSISNullSoft Scriptable Install System安装程序。如果我们查看静默选项我们会发现/D是我们影响安装目录的方式。所以我们会通过choco install notepadplusplus.install -ia
>"'/D=E:\SomeDirectory\somebody\npp'"- 请注意,我们正在查看虚拟的特定包(尽管您也可以使用 notepadplusplus 执行相同的操作)。
有没有更好的办法?绝对,看到无处不在的安装目录开关!
## winget
[微软官方文档](https://learn.microsoft.com/zh-cn/windows/package-manager/)
[winget-GitHub](https://github.com/microsoft/winget-cli/releases)
winget 是微软官方的包管理器。虽没有chocolatey受欢迎但还是可以的
### 安装
#### 应用商店安装
![image-1680681449718](https://local.wuanwanghao.top:9000/test/test/image-1680681449718.png)
#### 安装包安装
前往[winget-GitHub](https://github.com/microsoft/winget-cli/releases) 下载你需要安装版本的安装包 ```assest``` 下,文件后戳为 ```msixbundle``` 的安装包
下载完成后双击安装
### 使用
重新打开一个cmd 窗口
> install 安装给定的程序包
show 显示包的相关信息
source 管理程序包的来源
search 查找并显示程序包的基本信息
list 显示已安装的程序包
upgrade 显示并执行可用升级
uninstall 卸载给定的程序包
hash 哈希安装程序的帮助程序
validate 验证清单文件
settings 打开设置或设置管理员设置
features 显示实验性功能的状态
export 导出已安装程序包的列表
import 安装文件中的所有程序包
```
C:\Users\Hasee>winget --help
Windows 程序包管理器(预览) v1.5.441-preview
版权所有 (C) Microsoft Corporation。保留所有权利。
WinGet 命令行实用工具可从命令行安装应用程序和其他程序包。
使用情况: winget [<命令>] [<选项>]
下列命令有效:
install 安装给定的程序包
show 显示包的相关信息
source 管理程序包的来源
search 查找并显示程序包的基本信息
list 显示已安装的程序包
upgrade 显示并执行可用升级
uninstall 卸载给定的程序包
hash 哈希安装程序的帮助程序
validate 验证清单文件
settings 打开设置或设置管理员设置
features 显示实验性功能的状态
export 导出已安装程序包的列表
import 安装文件中的所有程序包
如需特定命令的更多详细信息,请向其传递帮助参数。 [-?]
下列选项可用:
-v,--version 显示工具的版本
--info 显示工具的常规信息
-?,--help 显示选定命令的帮助信息
--wait 提示用户在退出前按任意键
--logs,--open-logs 打开默认日志位置
--verbose,--verbose-logs 启用 WinGet 的详细日志记录
--disable-interactivity 禁用交互式提示
可在此找到更多帮助: "https://aka.ms/winget-command-help"
```
## Scoop
Scoop 是一款Windows下的命令行软件管理工具
简单来说,他比winget更强大(只是不够本土化,winget的软件本土化做的要更好一些,但对我来说在环境管理方面,scoop也有不可替代性)
### 安装:
打开 PowerShell 终端 (version 5.1 or later) 然后 运行:
[项目地址github](https://github.com/ScoopInstaller/Scoop)
[安装文档github](https://github.com/ScoopInstaller/Install)
#### 非管理员安装
```shell
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser #可选:第一次需要执行远程脚本
irm get.scoop.sh | iex
```
#### 管理员安装
```
irm get.scoop.sh -outfile 'install.ps1'
.\install.ps1 -RunAsAdmin -ScoopDir 'D:\env\Scoop' -ScoopGlobalDir 'D:\env\Scoop' -NoProxy
```
#### 指定环境变量
两者的值可以设为一致
```SCOOP``` 软件用户安装目录- 命令里 ScoopDir
```SCOOP_GLOBAL``` 软件的全局安装目录- 命令里 ScoopGlobalDir
### 使用
```
C:\Users\Hasee>scoop
Usage: scoop <command> [<args>]
Available commands are listed below.
Type 'scoop help <command>' to get more help for a specific command.
Command Summary
------- -------
alias Manage scoop aliases
bucket Manage Scoop buckets
cache Show or clear the download cache
cat Show content of specified manifest.
checkup Check for potential problems
cleanup Cleanup apps by removing old versions
config Get or set configuration values
create Create a custom app manifest
depends List dependencies for an app, in the order they'll be installed
download Download apps in the cache folder and verify hashes
export Exports installed apps, buckets (and optionally configs) in JSON format
help Show help for a command
hold Hold an app to disable updates
home Opens the app homepage
import Imports apps, buckets and configs from a Scoopfile in JSON format
info Display information about an app
install Install apps
list List installed apps
prefix Returns the path to the specified app
reset Reset an app to resolve conflicts
search Search available apps
shim Manipulate Scoop shims
status Show status and check for new app versions
unhold Unhold an app to enable updates
uninstall Uninstall an app
update Update apps, or Scoop itself
virustotal Look for app's hash or url on virustotal.com
which Locate a shim/executable (similar to 'which' on Linux)
```
```
scoop install nodejs
Installing 'nodejs' (18.4.0) [64bit]
node-v18.4.0-win-x64.7z (17.3 MB) [===================================] 100%
Checking hash of node-v18.4.0-win-x64.7z ... ok.
Extracting node-v18.4.0-win-x64.7z ... done.
Linking ~\scoop\apps\nodejs\current => ~\scoop\apps\nodejs\18.4.0
Persisting bin
Persisting cache
Running post_install script...
'nodejs' (18.4.0) was installed successfully!
```
#### 安装缓慢
可以指定环境变量 ```HTTP_PROXY``` 设置代理地址来加速
### 卸载
直接删除 ```SCOOP``` ```SCOOP_GLOBAL``` 环境变量所指的文件夹 可以完全删除

@ -0,0 +1,23 @@
---
icon: edit
date: 2023-02-15
category:
- 系统配置
headerDepth: 5
---
# windows 开始和关闭休眠模式,更换休眠文件保存位置
cmd 管理员模式执行命令
```cmd
powercfg -h off 关闭休眠模式 ,并删除休眠文件
powercfg -h on 开启休眠模式
```
使用“windows+R”组合键进入运行输入“regedit”命令。
![1676471193767](https://local.wuanwanghao.top:9000/test/test/1676471193767.png)
进入 ```计算机\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\BackupRestore\FilesNotToBackup```
ControlSet001 可能有多个 ControlSet002 ControlSet003 。。。有的话就全部修改
将FilesNotToBackup下的Power Management 项值从```\hiberfil.sys```修改为```盘符:\hiberfil.sys```
![image-1676471336708](https://local.wuanwanghao.top:9000/test/test/image-1676471336708.png)

@ -0,0 +1,11 @@
---
icon: edit
date: 2022-07-04
category:
- 内网穿透
headerDepth: 5
---
# zerotier Ping 不工作
[zerotier 官网相关解决方案](https://docs.zerotier.com/zerotier/troubleshooting/)

@ -0,0 +1,11 @@
---
icon: edit
date: 2022-07-04
category:
- 内网穿透
headerDepth: 5
---
# zerotier搭建moon模式
[zerotier搭建moon模式](https://blog.csdn.net/zetion_3/article/details/124046219)

@ -0,0 +1,143 @@
---
icon: edit
date: 2023-04-06
category:
- Linux
tag:
- tar
- zip
- uzip
- linux
headerDepth: 5
---
# zip unzip tar 命令使用
## tar
tar命令参数前面加”-"与不加“-”的区别:
tar命令参数前面加不加“-”执行命令的结果是没有区别的区别只要是在于linux风格方面加“-”属于System V风格不加“-”属于BSD风格所以在使用tar命令的时候它的参数加不加“-”结果是一样的,看个人的使用方式;
### 常用参数:
tar命令的常用参数
>-z 是否同时具有gz属性
-j 是否同时具有bz2属性
-J 是否同时具有xz属性
-x 解压缩、提取打包的内容
-t 查看压缩包内容
-c 建立一个压缩,打包文档
-C 切换到指定目录,表示指定解压缩包的内容和打包的内容存放的目录
-v 显示压缩或者打包的内容
-f 使用文件名在f后面要接压缩后的文件的名字只要用到tar命令-f选项是必须要用的-f参数在使用的时候一定排在其他参数的后面在最右边
-p 保留备份数据的原本权限与属性,常用于备份(-c重要的配置文件
-P 保留绝对路径
### 打包
#### 普通打包
```
tar -cvf 压缩后的文件名.tar 要压缩的目录或文件
```
#### 压缩打包
##### -z 用于gzip压缩方式 文件名.tar.gz
```shell
tar -zcvf 压缩后的文件名.tar.gz 要压缩的目录或文件
```
##### -j 用于bzip2压缩方式 文件名.tar.bz2
```shell
tar -jcvf 压缩后的文件名.tar.bz2 要压缩的目录或文件
```
##### -J 用于xz压缩方式 文件名.tar.xz
```shell
tar -Jcvf 压缩后的文件名.tar.xz 要压缩的目录或文件
```
##### 压缩格式比较:
压缩速度gz > bz2 > xz
压缩率xz > bz2 > gz
#### 解压
```shell
#不知道压缩格式解压自动识别
tar -xvf 文件名.压缩格式自动识别
# 指定gz
tar-zxvf 文件名.tar.gz
# 指定bz2
tar-jxvf 文件名.tar.bz2
# 指定xz
tar-Jxvf 文件名.tar.xz
```
>在解压gz压缩方式压缩文件的时候并不需要加上``` -z ```,直接用参数-xf即可另外两种压缩方式 ```-j``` 和 ```-J``` 在解压的时候一样因为tar命令会自动选择解压之后压缩文件还在如果不指定解压出来的文件保存在哪里那么会直接解压在当前目录
## zip
### 基本用法:
zip [参数] [压缩包名] [压缩的目录或者文件的路径]
### 常用参数:
zip命令的常用参数
>-m 将文件压缩后,删除原文件
-o 将压缩文件内的所有文件的最新变动时间设为压缩的时间
-q 安静模式,在压缩的时候不显示指令执行的过程
-r 递归压缩,将自定目录下的所有子文件以及文件一起处理
-x ”文件列表“,压缩时排除文件列表中的文件
### 使用
**1.正常压缩,不加-q选项显示压缩的过程**
```shell
zip -r 压缩后的文件名 目录
```
**2.加上-q选项安静模式输出不显示压缩的过程**
```
zip -q -r 压缩后的文件名 目录
```
**3.压缩多个文件 因为压缩的全是文件,所以可以不用加上-r选项**
```
zip test.zip test1.txt test2.txt test3.txt
```
**结果会将test1.txt test2.txt test3.txt 三个文件压缩进入 test.zip**
**4.压缩文件跟目录 因为压缩目标中包含目录 所以要加 -r**
```
zip -r test.zip test1.txt test2.txt test
```
**结果会将test1.txt test2.txt 两个文件 和test目录 压缩进入 test.zip**
## unzip
### 基本用法:
unzip [参数] [压缩文件] -d [目录] //如果不是用括号里面的内容,则解压文件在当前工作目录
### 常用参数:
unzip命令的常用参数
>-c 将解压缩的结果显示到屏幕上(显示每一个目录下的每一个文件的内容),同时对字符做适当的转换,但是并没有解压压缩包
-l 显示压缩文件内所包含的文件
-t 检查压缩文件是否正确
-v 执行时显示压缩文件的详细信息
-q 安静模式,执行时不显示任何信息
-d 指定文件解压后存储的目录
-x 指定不要处理压缩文件中的那些文件
### 使用
**1.解压 并列出解压结果**
```shell
unzip -c test.zip
```
**2.列出zip 包里面的文件**
```shell
unzip -l test.zip
```
**3.检查压缩文件是否正确**
```shell
unzip -t test.zip
```
**4.不解压压缩文件查看压缩包里面的内容(查看显示的文件列表还包含压缩比率)**
```shell
unzip -v test.zip
```
**4.解压缩到指定文件**
```shell
unzip test.zip -d /opt
```

@ -0,0 +1,11 @@
---
icon: edit
date: 2022-07-05
category:
- cpp
headerDepth: 5
---
# 【CMake】vcpkg + CMake 集成Clion
[【CMake】vcpkg + CMake](https://blog.csdn.net/qq_43331089/article/details/124494099)

@ -0,0 +1,14 @@
---
icon: edit
date: 2021-09-15
category:
- 系统配置
tag:
- linux
headerDepth: 5
---
# 一款酷酷的Linux系统实时监测工具Netdata的安装与使用
### 转载:
https://blog.luvying.com/archives/linux-monitor-netdata

File diff suppressed because it is too large Load Diff

@ -0,0 +1,22 @@
---
icon: edit
date: 2023-03-06
category:
- 私人配置
headerDepth: 5
---
# 各个数据库账号密码
mysql
local.wuanwanghao.top:3307 root ks125930.
local.wuanwanghao.top:3307 root ks125930.
sqlserver
local.wuanwanghao.top:1433 ```SA Ks125930.``` ```wanghao ks125930.```
redis
local.wuanwanghao.top:6379 无
mongodb
local.wuanwanghao.top:27017 root ks125930.

@ -0,0 +1,73 @@
---
icon: edit
date: 2023-04-02
category:
- 系统配置
headerDepth: 5
---
# 各种软件应用,编程语言开发工具包默认安装路径环境变量配置
# 编程语言
## nodejs:
### 环境变量
NODE_HOME: sdk 路径
NODE_PATH: nodejs 查找包的路径 一般指全局安装路径下 node_modules文件夹
### 配置:
```prefix``` 全局安装node_cache的路径
```cache``` 安装node_cache缓存位置
#### 命令
```shell
npm config set prefix "sdk 路径\node_global"
npm config set cache "sdk 路径\node_cache"
```
#### 配置文件
也可以在用户目录下修改```.npmrc```文件来指定
```
prefix=sdk 路径\node_global
cache=sdk 路径\node_cache
```
### path 修改
path 需配置添加 node_global路径 ,和 %NODE_HOME%\bin
## java
### 环境变量
JAVA_HOME: sdk路径
### path 修改
path 需配置添加 %JAVA_HOME%\bin
## golang
### 环境变量
GOROOT: sdk路径
GOPATH: 依赖包安装路径
### path 修改
path 需配置添加 %GOROOT%\bin ,%GOPATH%\bin
## kotlin
### 环境变量
KONAN_DATA_DIR: 数据缓存路径
# 工具
## gradle
### 环境变量
GRADLE_HOME: gradle安装路径
GRADLE_USER_HOME: 用户缓存数据路径
### path 修改
path 需配置添加 %GRADLE_HOME%\bin
## android
### 环境变量
ANDROID_SDK_ROOT: sdk路径
ANDROID_SDK_HOME: 用户缓存和虚拟机数据路径,
## vcpkg
### 环境变量
VC_PKG_HOME: vcpkg 安装路径
VCPKG_DEFAULT_BINARY_CACHEvcpkg 下载二进制安装包缓存路径
### path 修改
path 需配置添加 %VC_PKG_HOME%

@ -0,0 +1,67 @@
---
icon: edit
date: 2021-09-26
category:
- 网站搭建
tag:
- SSL
- 域名
- HTTPS
headerDepth: 5
---
# 域名添加SSL证书
# 域名添加SSL证书
> 我们的服务器购买域名并解析后,发现访问的时候搜索栏一直显示不安全,这样我们搭建的网站很难吸引到人过来访问,觉得咱们的网站是钓鱼网站
![image.png](/upload/2021/09/image-91fa2295488f4ebfb10b374d1835b6ae.png)
这时我们就需要给域名添加SSL证书了
## 操作指南
### 步骤1添加一键 HTTPS 域名
登录 [证书管理控制台](https://console.cloud.tencent.com/ssl),并单击左侧菜单栏一键 **HTTPS**,进入一键 **HTTPS**管理页面。
在一键 **HTTPS**管理页面中,单击一键添加。如下图所示:
>说明:
若你是首次使用,请在弹出的授权窗口中,授予对应权限。
![](https://main.qcloudimg.com/raw/e327528f08706299fef120e04c993099.png)
在弹出的 “一键添加” 窗口中,配置相关信息。如下图所示:
![](https://main.qcloudimg.com/raw/5e8f1474ff34ca297f5ccf9f7ae57e6a.png)
**填写域名**:请输入您需要进行一键 HTTPS 的域名。
>说明
填写的域名需要在工信部完成备案,否则将无法进行接入。详情请参见 备案概述。
**选择证书**:请选择已成功申请的证书。
>说明
选择的证书需与填写域名输入框填写的域名对应。例如,填写的域名为 ```cloud.tencent.com```,则选择绑定域名为 ```cloud.tencent.com``` 的证书。
**源站地址**:请根据您的实际需求选择**IP**与**域名**。
- **IP**:请输入需要防护网站的真实 IP 源站地址,即源站的公网 IP 地址。
- **域名**:请输入需要防护网站的真实源站域名。
**强制 HTTPS**:开启该功能,浏览器端的每个 HTTP 请求都会被跳转成 HTTPS 请求。例如,当浏览器使用 HTTP 协议访问 ```http://cloud.tencent.com ```时将返回302状态码重定向到 HTTPS 协议访问 ```https://cloud.tencent.com```。
**回源协议** 开启该功能,腾讯云将使用 HTTP 协议访问源站。例如,当浏览器使用 HTTP 或 HTTPS 协议访问 ```cloud.tencent.com``` 时,无论 HTTP 或 HTTPS 协议都将使用 HTTP 协议访问源站。
**回源端口**请根据您的实际需求选择回源端口。默认情况下支持443与8443若您开启回源协议则为80与8080。
单击确定,即可生成配置实例。如下图所示:
![](https://main.qcloudimg.com/raw/2c548a3cf3bc61f73512a57150319cec.png)
### 步骤2配置 CNAME 记录
>说明:
> - 添加一键 HTTPS 域名后,还需配置对应的 CNAME 记录后,接入才可正常生效。
> - 配置 CNAME 记录步骤以腾讯云配置 CNAME 记录为例,若您的一键 HTTPS 域名解析未在 DNSPod DNS 解析托管,具体操作请咨询您的域名解析商或将域名托管至 DNSPod DNS 解析后,再进行配置 CNAME 记录。详情请参见 域名托管至 DNSPod DNS 解析。
**一键添加 CNAME 记录**
手动添加 CNAME 记录
>说明
若您的域名解析已在 DNSPod DNS 解析进行托管,可直接一键添加 CNAME 记录。
在 "一键 HTTPS" 管理页面,查看您需要进行配置 CNAME 记录的实例,单击 + 。如下图所示:
![](https://main.qcloudimg.com/raw/29802e182d7b4ea87573c07df81ec119.png)
在弹出的 “温馨提示” 窗口中,单击确定。即可添加记录。如下图所示:
![](https://main.qcloudimg.com/raw/c0efc2dc88bb465e19f3b58e960f7c1e.png)

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save