初始化-首次提交

This commit is contained in:
root 2022-02-28 23:07:00 +08:00
commit 11e721f594
26 changed files with 3316 additions and 0 deletions

1
.obsidian/app.json vendored Normal file
View File

@ -0,0 +1 @@
{}

3
.obsidian/appearance.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"baseFontSize": 16
}

15
.obsidian/core-plugins.json vendored Normal file
View File

@ -0,0 +1,15 @@
[
"file-explorer",
"global-search",
"switcher",
"graph",
"backlink",
"page-preview",
"note-composer",
"command-palette",
"editor-status",
"markdown-importer",
"word-count",
"open-with-default-app",
"file-recovery"
]

1
.obsidian/hotkeys.json vendored Normal file
View File

@ -0,0 +1 @@
{}

98
.obsidian/workspace vendored Normal file
View File

@ -0,0 +1,98 @@
{
"main": {
"id": "a32a17ad4cdacd00",
"type": "split",
"children": [
{
"id": "2480116cbf7e41ff",
"type": "leaf",
"state": {
"type": "empty",
"state": {}
}
}
],
"direction": "vertical"
},
"left": {
"id": "f02df00dae391176",
"type": "split",
"children": [
{
"id": "7d6c46e25b82a62c",
"type": "tabs",
"children": [
{
"id": "914594b0e21a5aac",
"type": "leaf",
"state": {
"type": "file-explorer",
"state": {}
}
},
{
"id": "69a36f77ce322f8d",
"type": "leaf",
"state": {
"type": "search",
"state": {
"query": "",
"matchingCase": false,
"explainSearch": false,
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical"
}
}
}
]
}
],
"direction": "horizontal",
"width": 300
},
"right": {
"id": "e66ca0b0c34a1e7f",
"type": "split",
"children": [
{
"id": "1cd91799f12135b0",
"type": "tabs",
"children": [
{
"id": "07f4554ee5b95f3d",
"type": "leaf",
"state": {
"type": "backlink",
"state": {
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical",
"showSearch": false,
"searchQuery": "",
"backlinkCollapsed": false,
"unlinkedCollapsed": true
}
}
}
]
}
],
"direction": "horizontal",
"width": 300,
"collapsed": true
},
"active": "2480116cbf7e41ff",
"lastOpenFiles": [
"Untitled.md",
"front_end/js/js监听键盘键盘输入.md",
"front_end/vue/nodejs安装命令.md",
"front_end/vue/element upload手动文件上传多文件上传.md",
"proxy/FRP内网穿透.md",
"proxy/Ubuntu install 花生壳.md",
"front_end/vue/vue引入百度地图.md",
"ubuntu/MediaWiki搭建以及pivot皮肤配置.md",
"network/VPN服务器搭建以及使用(L2TP类型).md",
"elk/es、logstash安装.md"
]
}

View File

@ -0,0 +1,30 @@
* ### 下载帮助镜像portainer/helper-reset-password
```shell
docker pull portainer/helper-reset-password
```
* ### 查看portainer container id
```shell
docker container ls
```
![1638772640815.png](http://39.107.103.48:8600//blog/admin/png/2021/12/6/1638772640815.png)
* ### 查看 portainer 的挂载信息
```shell
docker inspect [portainer 容器id]
```
![1638772824025.png](http://39.107.103.48:8600//blog/admin/png/2021/12/6/1638772824025.png)
* ### 停止运行的portainer
```shell
docker stop [portainer 容器id]
```
* ### 运行重置命令
```shell
docker run --rm -v [挂载信息] portainer/helper-reset-password
```
![1638773641145.png](http://39.107.103.48:8600//blog/admin/png/2021/12/6/1638773641145.png)

157
elk/es、logstash安装.md Normal file
View File

@ -0,0 +1,157 @@
es、logstash安装
================
* 安装包准备(下载好之后上传至linux服务器)
* elasticsearch https://repo.huaweicloud.com/elasticsearch/
* ik分词器 https://github.com/medcl/elasticsearch-analysis-ik/releases
* logstash https://repo.huaweicloud.com/logstash/
* kibana https://repo.huaweicloud.com/kibana/
* elasticsearch-head https://github.com/mobz/elasticsearch-head
* node.js https://nodejs.org/en/download/
* elasticsearch
* 解压安装elasticsearch
```bash
tar -zxvf <elasticsearch-name>
```
* 配置elasticsearch.yml文件
* 打开配置文件
```bash
vim config/elasticsearch.yml
```
* 在配置文件最下面输入以下内容后 wq保存退出
```yaml
node.name: node-1
cluster.initial_master_nodes: "node-1"
network.host: 0.0.0.0
http.port: 9200 #端口
http.cors.enabled: true #开启跨域
http.cors.allow-origin: "*"
```
* 启动elasticsearch
* 直接启动-执行bin目录下的elasticsearch
```bash
./bin/elasticsearch
```
* 后台启动-执行bin目录下的elasticsearch 加上-d
```
./bin/elasticsearch -d
```
使用ps kill命令杀掉当前elasticsearch后台
```bash
ps -ef|grep elasticsearch
kill -9 <PID>
```
* 启动出现max virtual memory areas vm.max\_map\_count \[65530\] is too low, increase to at least \[262144\]解决办法
* 打开/etc/sysctl.conf
```bash
sudo /etc/sysctl.conf
```
* 在最下面添加以下内容 然后:wq保存退出
```bash
vm.max_map_count=262144
```
* 执行/sbin/sysctl -p立即生效
```bash
sudo /sbin/sysctl -p
```
* ik 分词器安装(版本号要一致)
```bash
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.3.0/elasticsearch-analysis-ik-6.3.0.zip
```
* logstash安装
* 解压安装logstash
```bash
tar -zxvf <logstash-name>
```
* 配置启动文件
* 在config文件目录下创建mysql.conf启动文件
```bash
input {
jdbc {
jdbc_connection_string => "jdbc:mysql://192.168.3.51:3306/kf?serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true&allowMultiQueries=true"
jdbc_user => "lduan"
jdbc_password => "359"
jdbc_driver_library => "/home/gd-service/software/mysql-connector-java-8.0.23/mysql-connector-java-8.0.23.jar"
jdbc_driver_class => "com.mysql.cj.jdbc.Driver"
# 定时器 多久执行一次SQL默认是一分钟
schedule => "* * * * *"
#是否清除 last_run_metadata_path 的记录,如果为真那么每次都相当于从头开始查询所有的数据库记录
clean_run => "false"
#记录字段保存的位置
last_run_metadata_path => "/home/gd-service/software/elk/logstash-7.8.0/station_parameter.txt"
# statement => "SELECT * FROM purchase_history"
# 执行的sql 文件路径+名称
statement_filepath => "/home/gd-service/software/elk/logstash-7.8.0/mysql/jdbc.sql"
#是否分页
jdbc_paging_enabled => "true"
jdbc_page_size => "5000"
# 索引类型
type => "_doc"
#是否需要记录某列的值,用于实时同步更新
use_column_value => true
#需要记录的字段一般用于记录主键Id或者更新时间用于sql查询最新
tracking_column => "index"
#写入es数据的key,默认会被转成小写,该字段用于控制是否小写。
lowercase_column_names => false
}
stdin{
}
}
#ElasticSearch中默认使用UTC时间,和中国时间相差8小时加入以下配置
filter {
ruby {
code => "event.set('timestamp',event.get('@timestamp').time.localtime+8*60*60)"
}
ruby {
code => "event.set('@timestamp',event.get('timestamp'))"
}
mutate {
remove_field => ["timestamp"]
}
# ruby {
# code => "event.set('myTimeField',event.get('myTimeField').time.localtime+8*60*60)"
# }
}
#filter { json { source => "message" remove_field => ["message"] } }
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "product"
document_type => "_doc"
document_id => "%{index}"
}
stdout{
# JSON格式输出
codec => "json_lines"
}
}
```
* 启动logstash
* 直接启动-执行bin目录下的logstash
```bash
./logstash -f ../config/mysql.conf
```

View File

@ -0,0 +1,9 @@
```javascript
document.addEventListener('keydown', function(e){
if (e.keyCode == 83 && (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey)){
#preventDefault() 方法会取消该事件,比如ctrl+s会保存当前网页此方法可以取消这些原本的操作写上我们要执行的操作给他覆盖掉
e.preventDefault();
alert('save');
}
});
```

View File

@ -0,0 +1,260 @@
#### 自定义文件上传
```
<template>
<el-dialog
title="匿名反馈"
:visible.sync="visible"
@close="closeFeedbackDialog"
>
<el-form>
<el-form-item :label-position="labelPosition" label="附件">
<!--
limit 最多选择一个文件进行上传,
http-request 上传所执行的方法,上传多个文件便执行多次
auto-upload 选中文件后自动进行上传
-->
<el-upload
style="width:100%"
drag
action="/"
ref="upload"
:limit="1"
:http-request="httpRequest"
:auto-upload="false"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">
附件总大小不能超过100MB
</div>
</el-upload>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="closeFeedbackDialog">取 消</el-button>
<el-button
type="primary"
@click="sendFeedback"
v-loading.fullscreen.lock="fullscreenLoading"
element-loading-text="邮件正在发送请稍等"
>确 定</el-button
>
</div>
</el-dialog>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
visible: false,
feedback: {
title: '匿名反馈',
to: '123@qq.com'
},
labelPosition: 'top',
fileList: [],
fileData: null,
fileSize: 0,
fullscreenLoading: false
}
},
methods: {
// 关闭对话框并重置
closeFeedbackDialog() {
this.reset()
this.visible = false
},
// param中获取文件对象 进行上传,如果多个文件会执行多次此方法发送多个请求
httpRequest(param) {
this.fileSize = 0
this.fileSize = param.file.size
//验证文件大小
if (this.fileSize / 1024 / 1024 >= 100) {
this.$message.error('附件总大小不能超过100MB')
return
}
this.fileData = new FormData();
//获取文件
this.fileData.append('files', param.file)
//如果需要其他参数可以使用append进行添加
this.fileData.append('to', this.feedback.to)
this.fileData.append('title', this.feedback.title)
//上传地址
let url = 'http://192.168.3.101:60001/mail/send'
//配置请求头信息
let config = {
headers: {
'Content-Type': 'multipart/form-data'
}
}
//开启加载
this.fullscreenLoading = true
//进行请求
axios.post(url, this.fileData, config).then(res => {
//关闭加载
this.fullscreenLoading = false
if (res.data.code === 1) {
this.$message.success('发送成功')
//上传成功执行关闭方法关闭对话框
this.closeFeedbackDialog()
} else {
this.$message.error(res.data.msg)
}
}).catch(error=>{
this.fullscreenLoading = false
this.$message.error("发送邮件时出现异常,请联系管理员!")
})
},
//发送邮件
sendFeedback() {
//提交时自动执行httpRequest方法保存要上传的文件到this.fileData
this.$refs.upload.submit()
},
reset() {
this.fileList = []
}
}
}
</script>
<style>
.el-upload {
width: 100% !important;
}
.el-upload-dragger {
width: 100% !important;
}
</style>
```
#### 一次请求上传多个文件(推荐使用)
```
<template>
<el-dialog
title="匿名反馈"
:visible.sync="visible"
@close="closeFeedbackDialog"
>
<el-form>
<el-form-item :label-position="labelPosition" label="附件">
<!--
file-list 选中的文件列表,
http-request 上传所执行的方法,上传多个文件便执行多次
auto-upload 选中文件自动上传
-->
<el-upload
style="width:100%"
class="upload"
drag
action="/"
multiple
ref="upload"
:http-request="httpRequest"
:auto-upload="false"
:file-list="fileList"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">
附件总大小不能超过100MB
</div>
</el-upload>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="closeFeedbackDialog">取 消</el-button>
<el-button
type="primary"
@click="sendFeedback"
v-loading.fullscreen.lock="fullscreenLoading"
element-loading-text="邮件正在发送请稍等"
>确 定</el-button
>
</div>
</el-dialog>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
visible: false,
feedback: {
title: '匿名反馈',
to: '123@qq.com'
},
labelPosition: 'top',
fileList: [],
fileData: null,
fileSize: 0,
fullscreenLoading: false
}
},
methods: {
// 关闭对话框并重置
closeFeedbackDialog() {
this.reset()
this.visible = false
},
// this.$refs.upload.submit() 提交时会自动调用 httpRequest方法在param获取文件对象。
httpRequest(param) {
this.fileData.append('files', param.file)
this.fileSize += param.file.size
},
//发送邮件
sendFeedback() {
this.fileSize = 0
this.fileData = new FormData();
//提交时自动执行httpRequest方法保存要上传的文件到this.fileData
this.$refs.upload.submit()
//验证文件大小
if (this.fileSize / 1024 / 1024 >= 100) {
this.$message.error('附件总大小不能超过100MB')
return
}
//如果需要其他参数可以使用append进行添加
this.fileData.append('to', this.feedback.to)
this.fileData.append('title', this.feedback.title)
//上传地址
let url = 'http://192.168.3.101:60001/mail/send'
//配置请求头信息
let config = {
headers: {
'Content-Type': 'multipart/form-data'
}
}
//开启加载
this.fullscreenLoading = true
//进行请求
axios.post(url, this.fileData, config).then(res => {
//关闭加载
this.fullscreenLoading = false
if (res.data.code === 1) {
this.$message.success('发送成功')
//上传成功执行关闭方法关闭对话框
this.closeFeedbackDialog()
} else {
this.$message.error(res.data.msg)
}
}).catch(error=>{
this.fullscreenLoading = false
this.$message.error("发送邮件时出现异常,请联系管理员!")
})
},
reset() {
this.fileList = []
}
}
}
</script>
<style>
.el-upload {
width: 100% !important;
}
.el-upload-dragger {
width: 100% !important;
}
</style>
```

View File

@ -0,0 +1,40 @@
nodejs安装命令
==============
* 安装nodejs
```bash
sudo apt-get install nodejs
```
* 安装npm
```bash
sudo apt-get install npm
```
* 设置淘宝镜像源
```bash
npm config set registry https://registry.npm.taobao.org
```
* 获取当前镜像源
```bash
npm config get registry
```
* 安装淘宝的cnpm然后在使用时直接将npm命令替换成cnpm命令即可
```bash
npm install -g cnpm --registry=https://registry.npm.taobao.org
```
* 安装vue
```bash
sudo npm install -g vue-cli
```
* 查看版本
```bash
node -v
npm -v
vue -V
```

View File

@ -0,0 +1,98 @@
vue引入百度地图
====================================
* ### 首先安装百度地图依赖
```bash
npm install vue-baidu-map --save
```
* ### 申请百度地图开放平台百度地图密钥
* 申请链接http://lbsyun.baidu.com/index.php?title=jspopular/guide/getkey根据网站提示填写应用信息。
* 在应用类型出选择浏览器端
* ip白名单填写\*号
* ### 在main.js中全局注册
```js
import Vue from 'vue'
//添加百度地图
import BaiduMap from 'vue-baidu-map'
Vue.use(BaiduMap,{
ak:'GHYWGm6cKODTU3BzuKDlEqARxc2ZEf3c'
})
```
* ### 如果使用的是quasar-cli
* 在src/boot 下创建启动文件baiduMap.js 添加以下内容
```js
import Vue from 'vue'
//添加百度地图
import BaiduMap from 'vue-baidu-map'
Vue.use(BaiduMap,{
ak:'你申请的百度地图开放平台应用key'
})
```
* 在quasar.conf.js文件中添加你的启动文件
```json
boot: [
'i18n',
'axios',
'baiduMap'
]
```
* ### 页面
```vue
<template>
<baidu-map
:center="center"
:zoom="zoom"
@ready="handler"
style="height: 1080px"
@click="getClickInfo"
:scroll-wheel-zoom="true"
>
</baidu-map>
</template>
<script>
export default {
name: "TestBaiDu",
data() {
return {
center: { lng: 109.45744048529967, lat: 36.49771311230842 },
zoom: 13
};
},
methods: {
handler({ BMap, map }) {
var point = new BMap.Point(109.49926175379778, 36.60449676862417);
map.centerAndZoom(point, 13);
var marker = new BMap.Marker(point); // 创建标注
map.addOverlay(marker); // 将标注添加到地图中
var circle = new BMap.Circle(point, 6, {
strokeColor: "Red",
strokeWeight: 6,
strokeOpacity: 1,
Color: "Red",
fillColor: "#f03",
});
map.addOverlay(circle);
var opts = {
width: 50, // 信息窗口宽度
height: 10, // 信息窗口高度
title: "北京", // 信息窗口标题
};
var infoWindow = new BMap.InfoWindow("三里屯", opts); // 创建信息窗口对象
map.openInfoWindow(infoWindow, map.getCenter()); // 打开信息窗口
},
getClickInfo(e) {
console.log(e.point.lng);
console.log(e.point.lat);
this.center.lng = e.point.lng;
this.center.lat = e.point.lat;
}
}
};
```

View File

@ -0,0 +1,32 @@
gitlab---create blank project and push
======================================
#### 1.点击new project创建新项目
#### 2.打开本地项目文件夹》右击点击git bash here
#### 3.初始化
```bash
git init
```
#### 4.添加远程git上传地址
```bash
git remote add origin git@192.168.3.51:A/B.git
```
> 注:"A" 处输入你的用户名 必须是用户名 邮箱会报错
> 注:"B" 处输入创建的项目名称 (小写)
#### 5.将本地项目上传至gitlab服务器
```bash
git add .
git commit -m '本次上传内容介绍'
git push origin master
```
> 注:如果上传过程出现错误 打开本地项目文件 删除.git 文件夹 从第三步开始在试一遍

View File

@ -0,0 +1,28 @@
Java CMD运行Jar出现乱码问题
===========================
### 一、设定CMD的编码为utf-8
##### 打开cmd输入以下命令
```bash
chcp 65001
```
##### cmd常用编码
| 字符编码 | 对应字符 |
| ----------- | -------- |
| GBK默认 | 936 |
| 美国英语 | 437 |
| utf-8 | 65001 |
### 二、规定执行Java时的编码方式
普通运行方式
java -jar project.jar
规定utf-8编码格式运行
java -Dfile.encoding=utf-8 -jar project.jar

View File

@ -0,0 +1,54 @@
```java
/**
* @author dss
* @date 2021/10/9
* @description:
*/
public enum AuditStatus{
NO_SUBJECT(0,"未提交"),
NO_AUDIT(2,"未审核"),
AUDIT(1,"审核通过");
@Getter
private final Integer code;
@Getter
private final String label;
AuditStatus(Integer code,String label){
this.code=code;
this.label=label;
}
/**
* 根据code获取对应的label
* @param code
* @return 形参code所对应的label值
* @throws Exception
*/
public static String getValueByCode(Integer code) throws Exception {
//获取Class对象
Class<?> clzz = AuditStatus.class;
// 获取所有枚举对象
Object[] objects = clzz.getEnumConstants();
//获取指定方法
Method coinLabel = clzz.getMethod("getLabel");
Method coinCode = clzz.getMethod("getCode");
//遍历所有枚举对象
for (Object obj : objects) {
//执行coinCode方法(getCode)该枚举的code值如果和形参code 的值相同则
if (coinCode.invoke(obj) == code) {
//执行coinLabel方法getLabel获取响应的label值进行返回
return coinLabel.invoke(obj).toString();
}
}
return null;
}
}
```

View File

@ -0,0 +1,169 @@
直接看码
========
```java
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author dss
* @projectName queueDemo
* @date 2021/12/1
* @description:
*/
public class QueueDemo01 {
public static void main(String[] args) {
//队列模拟库存 容量为10
Queue<ManTou> manTouQueue = new ArrayBlockingQueue<ManTou>(10);
//放入容量对象
Container container = new Container(manTouQueue);
//生产者线程自增
final AtomicInteger pCount = new AtomicInteger(1);
//消费者线程自增
final AtomicInteger cCount = new AtomicInteger(1);
//设置生产者线程名称
ThreadFactory producer = new ThreadFactory() {
public Thread newThread(Runnable r) {
return new Thread(r,"生产"+pCount.getAndIncrement()+"线");
}
};
//设置消费者线程名称
ThreadFactory consumer = new ThreadFactory() {
public Thread newThread(Runnable r) {
return new Thread(r,"北京"+cCount.getAndIncrement()+"店");
}
};
//生产者线程池
ExecutorService producers = Executors.newCachedThreadPool(producer);
//消费者线程池
ExecutorService consumers = Executors.newCachedThreadPool(consumer);
for (int i = 0; i < 5; i++) {
consumers.execute(new Consumer(container));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
producers.execute(new Producer(container));
}
}
}
//容器
class Container{
//馒头自增编号
private int no;
//馒头队列
private Queue<ManTou> manTouQueue;
Container(Queue<ManTou> manTouQueue){
this.manTouQueue=manTouQueue;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public Queue<ManTou> getQueue() {
return manTouQueue;
}
}
//产品
class ManTou{
//编号
private int no;
ManTou(int no){
this.no = no;
};
public int getNo() {
return no;
}
}
//生产
class Producer implements Runnable{
//容器
private Container container;
Producer(Container container){
this.container=container;
}
public void run() {
//循环生产
while (true){
//对容器进行同步 保证线程安全
synchronized (container){
//将生产馒头添加到队列
boolean flag = container.getQueue().offer(new ManTou(container.getNo()+1));
if (flag){
//编号加一
container.setNo(container.getNo()+1);
//记录生产的馒头
System.out.println(Thread.currentThread().getName()+"生产馒头"+container.getNo());
}else{
//提示队列已满请先消费
System.out.println("库存满了快去销售~");
}
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//消费
class Consumer implements Runnable{
//容器
private Container container;
Consumer(Container container){
this.container=container;
}
public void run() {
//循环销售
while (true){
synchronized (container){
//获取馒头
ManTou manTou = container.getQueue().poll();
if (manTou!=null){
//记录销售馒头
System.out.println(Thread.currentThread().getName()+"出售馒头"+manTou.getNo());
}else{
System.err.println("卖完了快去生产~");
}
System.err.println("当前库存"+container.getQueue().size());
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
```

View File

@ -0,0 +1,495 @@
java-queue(队列)
================
### 1\. 队列
#### 1.1 队列介绍
Queue用于模拟队列这种数据结构队列通常是指**先进先出**FIFO的容器。新元素插入offer到队列的尾部访问元素poll操作会返回队列头部的元素。通常队列不允许随机访问队列中的元素。
#### 1.2 关系图
![1638371649957.png](http://39.107.103.48:8600//blog/admin/png/2021/12/1/1638371649964.png)
#### 1.3 队列种类介绍
##### 1.3.1 双端队列
我们知道,`Queue`是队列,只能一头进,另一头出。
如果把条件放松一下允许两头都进两头都出这种队列叫双端队列Double Ended Queue学名 `Deque`
Java集合提供了接口 `Deque`来实现一个双端队列,它的功能是:
* 既可以添加到队尾,也可以添加到队首;
* 既可以从队首获取,又可以从队尾获取。
##### 1.3.2 阻塞队列
阻塞队列是一个支持两个附加操作的队列:
* 在队列为空时,获取元素的线程会等待队列变为非空;
* 当队列满时,存储元素的线程会等待队列可用。
因此,当一个线程试图对一个已经满了的队列进行入队列操作时,它将会被堵塞,除非有另一个线程做了出队列的操作;同样,当一个线程试图对一个空队列进行出队列操作时,它将会被阻塞,除非有另外一个线程进行了入队列的操作。
##### 1.3.3 非阻塞队列
基于锁的算法会带来一些活跃度失败的风险。如果线程在持有锁的时候因为阻塞I/O、页面错误、或其他原因发生延迟很可能所有的线程都不能工作了。一个线程的失败或挂起不应该影响其他线程的失败或挂起这样的算法称为**非阻塞算法**;如果算法的每一个步骤中都有一些线程能够继续执行,那么这样的算法称为**锁自由lock-free算法**。\*\*在线程间使用CAS进行协调这样的算法如果能构建正确的话它既是非阻塞的又是锁自由的。\*\*java中提供了基于CAS非阻塞算法实现的队列比较有代表性的有ConcurrentLinkedQueue和LinkedTransferQueue它们的性能一般比阻塞队列的好。
#### 1.4 queue常用队列
* **PriorityQueue**:非阻塞、非线程安全、无边界,支持优先级队列实现类。
* **ConcurrentLinkedQueue**:非阻塞、线程安全、无边界,基于链接节点的队列实现类。
* **ArrayBlockingQueue**:阻塞、线程安全、有边界,一旦创建容量不可改变实现类。
* **LinkedBlockingQueue**:阻塞、线程安全、可选有边界,一个由链表结构组成的可选有界阻塞队列实现类,如果未指定容量,那么容量将等于 `Integer.MAX_VALUE`
* **PriorityBlockingQueue**:阻塞、线程安全、无边界,支持优先级排序的无边界阻塞队列实现类。
* **DelayQueue**:阻塞、线程安全、无边界,使用优先级队列实现的无界阻塞队列实现类,只有在延迟期满时才能从中提取元素。
* **SynchronousQueue**:阻塞、线程安全、无数据队列,不存储元素、没有内部容量的阻塞队列实现类。
* **LinkedBlockingDeque**:阻塞、线程安全、无边界,由链表结构组成的可选范围双向阻塞队列实现类,如果未指定容量,那么容量将等于 `Integer.MAX_VALUE`
* **ArrayDeque**: 非阻塞、非线程安全、无边界数组双端队列当用作栈时性能优于Stack当用于队列时性能优于LinkedList
### 2\. 队列详解
#### 2.1 PriorityQueue
PriorityQueue即优先队列**优先队列的作用是能保证每次取出的元素都是队列中权值最小的**(优先队列每次取最小元素)。这里牵涉到了大小关系,**元素大小的评判可以通过元素本身的自然顺序natural ordering也可以通过构造时传入的比较器**Comparator
  PriorityQueue不允许放入 `null`元素。其通过堆实现具体说是通过完全二叉树complete binary tree实现的**小顶堆**任意一个非叶子节点的权值都不大于其左右子节点的权值也就意味着可以通过数组来作为PriorityQueue的底层实现。
  **定义一个PriorityQueue的方式有如下几种**
```java
//创建一个PriorityQueue队列初始化一个容量为11的且以自然顺序排序元素的优先队列
PriorityQueue<String> queue = new PriorityQueue<String>();
//创建一个PriorityQueue队列初始化指定大小的容量的优先队列且以自然顺序排列元素
queue = new PriorityQueue<String>(30);
//创建一个PriorityQueue队列包含collection
queue = new PriorityQueue<String>(new ArrayList<String>());
//创建一个PriorityQueue队列初始化指定大小(不能少于1)和比较器的优先队列
queue = new PriorityQueue<String>(30, new Comparator<String>(){
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
```
PriorityQueue有很多常用方法add、offer、poll、peek、element、remove、clear、size、isEmpty等关于其他方法可以查看API。
  **常用方法说明如下**
```java
//往优先队列中插入元素,插入元素失败时会抛出异常
boolean add(E e);
//往优先队列中插入元素插入元素失败时会返回false
boolean offer(E e);
//获取并删除队列的第一个元素或队列头部的元素删除元素失败时会返回null
E poll();
//获取队列第一个元素或队列头部的元素不删除队列中的元素获取不到返回null
E peek();
//获取队列第一个元素或队列头部的元素,不删除队列中的元素,获取不到会抛出异常
E element();
//从队列中删除元素的单个实例
E remove();
//删除优先级队列的所有内容
void clear();
//返回队列中存在的元素数
int size();
//判断改队列是否为空
boolean isEmpty();
```
#### 2.2 ConcurrentLinkedQueue
ConcurrentLinkedQueue是基于链接节点的无界线程安全队列。**此队列按照FIFO先进先出原则对元素进行排序**。队列的头部是队列中时间最长的元素,队列的尾部 是队列中时间最短的元素。新的元素插入到队列的尾部,队列获取操作从队列头部获得元素。当**多个线程共享访问一个公共collection时ConcurrentLinkedQueue是一个恰当的选择**此队列不允许使用null元素。
  **定义一个ConcurrentLinkedQueue的方式有如下几种**
```java
//创建一个ConcurrentLinkedQueue队列
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>();
//将其他类型的集合转为ConcurrentLinkedQueue队列
queue = new ConcurrentLinkedQueue<String>(new ArrayList<String>());
```
 ConcurrentLinkedQueue有很多常用方法add、offer、poll、peek、remove、clear、size、isEmpty等关于其他方法可以查看API。
#### 2.3 ArrayBlockingQueue
ArrayBlockingQueue是一个阻塞式的队列继承自AbstractBlockingQueue,间接的实现了Queue接口和Collection接口。底层以数组的形式保存数据(实际上可看作一个循环数组)。
  ArrayBlockingQueue通过使用**全局独占锁**实现同时**只能有一个线程进行入队或者出队操作**,有点类似在**方法上添加synchronized**。其中offer、poll操作通过简单的加锁进行入队出队操作而put、take则使用了条件变量实现如果队列满则等待如果队列空则等待然后分别在出队和入队操作中发送信号激活等待线程实现同步。另外相比LinkedBlockingQueueArrayBlockingQueue的size操作的结果是精确的因为计算前加了全局锁。
  **定义一个ArrayBlockingQueue的方式有如下几种**
```java
//创建一个ArrayBlockingQueue队列设置初始容量
ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(2);
//创建一个ArrayBlockingQueue队列设置初始容量和是否为公平锁
queue = new ArrayBlockingQueue<String>(2, false);
//设置初始容量和是否为公平锁并且将其他类型的集合转为ArrayBlockingQueue队列
queue = new ArrayBlockingQueue<String>(2, false, new ArrayList<String>());
```
ArrayBlockingQueue有很多常用方法add、offer、put、poll、take、element、peek、remove、clear、size、isEmpty等关于其他方法可以查看API。
  **常用方法说明如下**
```java
//将指定的元素插入到此队列的尾部里面调用了offer方法如果队列满了则抛出异常
boolean add(E e);
//将指定的元素插入到此队列的尾部(如果立即可行且不会超过该队列的容量),在成功时返回 true如果此队列已满则返回 false
boolean offer(E e);
//将指定的元素插入此队列的尾部,如果该队列已满则产生阻塞等待,直至可以添加元素为止
void put(E e);
//获取并移除此队列的头,如果此队列为空,则返回 null
E poll();
//获取并移除此队列的头部,如果没有元素则等待,直至获取元素为止
E take();
//获取但不移除此队列的头,如果此队列为空,则返回 null
E peek();
//从此队列中移除指定元素的单个实例
E remove();
```
#### 2.4 LinkedBlockingQueue
LinkedBlockingQueue是一个基于已链接节点的、范围任意的blocking queue。**此队列按FIFO先进先出排序元素**。队列的头部 是在队列中时间最长的元素。队列的尾部是在队列中时间最短的元素。新元素插入到队列的尾部,并且队列获取操作会获得位于队列头部的元素。链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可预知的性能要低。
  LinkedBlockingQueue中也有两个Node分别用来存放首尾节点并且里面有个初始值为0的原子变量count用来记录队列元素个数另外里面有两个ReentrantLock的独占锁分别用来控制元素入队和出队加锁其中takeLock用来控制同时只有一个线程可以从队列获取元素其他线程必须等待putLock控制同时只能有一个线程可以获取锁去添加元素其他线程必须等待。另外notEmpty和notFull用来实现入队和出队的同步。 另外由于出入队是两个**非公平独占锁**,所以**可以同时又一个线程入队和一个线程出队**,其实这个是个生产者-消费者模型。
  **定义一个LinkedBlockingQueue的方式有如下几种**
```java
//创建一个LinkedBlockingQueue队列初始容量为Integer.MAX_VALUE
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>();
//创建一个LinkedBlockingQueue队列设置初始容量
queue = new LinkedBlockingQueue<String>(30);
//设置初始容量为Integer.MAX_VALUE并且将其他类型的集合转为LinkedBlockingQueue队列
queue = new LinkedBlockingQueue<String>(new ArrayList<String>());
```
LinkedBlockingQueue有很多常用方法add、offer、put、poll、take、element、peek、remove、clear、size、isEmpty等关于其他方法可以查看API。
  **常用方法说明如下**
```java
//将对象塞入队列如果塞入成功返回true, 否则返回异常
boolean add(E e);
//将对象塞入到队列中如果设置成功返回true, 否则返回false
boolean offer(E e);
//将元素塞入到队列中,如果队列中已经满了,则该方法会一直阻塞,直到队列中有多余的空间
void put(E e);
//从队列中取对象,如果队列中没有对象,线程会一直阻塞,直到队列中有对象,并且该方法取得了该对象
E take();
//在给定的时间里从队列中获取对象时间到了直接调用普通的poll方法为null则直接返回null
E poll(long timeout, TimeUnit unit);
//获取队列中剩余长度
int remainingCapacity();
//从队列中移除指定的值
boolean remove(Object o);
//判断队列中是否包含该对象
public boolean contains(Object o);
//将队列中对象,全部移除,并加到传入集合中
int drainTo(Collection<? super E> c);
```
#### 2.5 PriorityBlockingQueue
 PriorityBlockingQueue是一个支持优先级的无界阻塞队列虽然此队列逻辑上是无界的**但是资源被耗尽时试图执行 add 操作也将失败**导致OutOfMemoryError错误。**默认情况下元素采用自然顺序升序排列。也可以自定义类实现compareTo()方法来指定元素排序规则或者初始化PriorityBlockingQueue时指定构造参数Comparator来对元素进行排序**。但需要注意的是不能保证同优先级元素的顺序。PriorityBlockingQueue也是基于最小二叉堆实现使用基于CAS实现的自旋锁来控制队列的动态扩容保证了扩容操作不会阻塞take操作的执行。
  由于这是一个优先级队列所以有个比较器comparator用来比较元素大小。l\*\*ock独占锁对象用来控制同时只能有一个线程可以进行入队出队操作。\*\*notEmpty条件变量用来实现take方法阻塞模式。这里没有notFull条件变量是因为这里的put操作是非阻塞的为啥要设计为非阻塞的是因为这是无界队列。
  **定义一个PriorityBlockingQueue的方式有如下几种**
```java
//创建一个PriorityBlockingQueue队列初始容量为11
PriorityBlockingQueue<String> queue = new PriorityBlockingQueue<String>();
//创建一个PriorityBlockingQueue队列设置初始容量
queue = new PriorityBlockingQueue<String>(12);
//将其他类型的集合转为PriorityBlockingQueue队列
queue = new PriorityBlockingQueue<String>(new ArrayList<String>());
//创建一个PriorityBlockingQueue队列初始化指定大小和比较器的优先队列
queue = new PriorityBlockingQueue<String>(12, new Comparator<String>(){
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
```
 PriorityBlockingQueue有很多常用方法add、offer、put、poll、take、element、peek、remove、clear、size、isEmpty等关于其他方法可以查看API。
  **常用方法说明如下**
```java
//向此队列添加指定的元素
boolean add(E o);
//将指定的元素插入到优先级队列中
boolean offer(E o);
//将指定的元素添加到优先级队列中
void put(E o);
//检索,但是不移除此队列的头,如果此队列为空,则返回 null
E peek();
//检索并移除此队列的头部,如果此队列中没有任何元素,则等待指定等待的时间(如果有必要)
E poll();
//检索并移除此队列的头部,如果此队列不存在任何元素,则一直等待
E take();
//判断队列中是否包含该对象
boolean contains(Object o);
//移除此队列中所有可用的元素,并将它们添加到给定 collection中
int drainTo(Collection<? super E> c);
```
#### 2.6 DelayQueue
DelayQueue是Delayed元素的一个无界阻塞队列**只有在延迟期满时才能从中提取元素**。该队列的头部是延迟期满后保存时间最长的Delayed元素。如果延迟都还没有期满则队列没有头部并且poll将返回null。
  DelayQueue中内部使用的是PriorityQueue存放数据使用ReentrantLock实现线程同步可知是阻塞队列。另外**队列里面的元素要实现Delayed接口**,一个是获取当前剩余时间的接口,一个是元素比较的接口,因为这个是有优先级的队列。
  **定义一个DelayQueue的方式有如下几种**
```java
public DelayQueue() {}
public DelayQueue(Collection<? extends E> c) {
this.addAll(c);
}
```
DelayQueue有很多常用方法add、offer、put、poll、take、element、peek、remove、clear、size、isEmpty等关于其他方法可以查看API。
  **常用方法说明如下**
```java
//将指定的元素插入此延迟队列
boolean add(E e);
//将指定的元素插入此延迟队列
boolean offer(E e);
//将指定的元素插入此延迟队列
void put(E e);
//检索但不删除此队列的头如果此队列为空则返回null
E peek();
//检索并删除此队列的头, 如果此队列没有延迟过期的元素则返回null
E poll();
//检索并删除此队列的头,如有必要,请等待直到延迟过期的元素在此队列上可用
E take();
//从指定队列中删除指定元素的单个实例(如果存在),无论它是否已过期
boolean remove(Object o);
//从此队列中删除所有可用的元素,并将它们添加到给定的集合中
int drainTo(Collection<? super E> c);
```
#### 2.7 SynchronousQueue
 SynchronousQueue是一个不存储元素、**没有内部容量的阻塞队列,其中每个插入操作必须等待另一个线程的对应移除操作**反之亦然。同步队列没有任何内部容量甚至连一个队列的容量都没有。不能在同步队列上进行peek因为仅在试图要移除元素时该元素才存在.除非另一个线程试图移除某个元素,否则也不能(使用任何方法)插入元素。**也不能迭代队列,因为其中没有元素可用于迭代**。队列的头是尝试添加到队列中的首个已排队插入线程的元素。如果没有这样的已排队线程,则没有可用于移除的元素并且 `poll()`将会返回null。对于其他collection方法例如containsSynchronousQueue作为一个空collection。
  对于正在等待的生产者和使用者线程而言,此类**支持可选的公平排序策略,默认情况下不保证这种排序**。但是,使用公平设置为 `true`所构造的队列可保证线程以FIFO的顺序进行访问。
  **定义一个SynchronousQueue的方式有如下几种**
```java
//创建一个SynchronousQueue队列不保证顺序
SynchronousQueue<String> queue = new SynchronousQueue<String>();
//创建一个SynchronousQueue队列保证顺序
queue = new SynchronousQueue<String>(true);
```
SynchronousQueue有很多常用方法add、offer、put、poll、take、drainTo等关于其他方法可以查看API。
  **常用方法说明如下**
```java
//如果另一个线程正在等待接收指定的元素,则将其插入此队列
boolean offer(E e);
//将指定的元素添加到此队列,如果有必要,等待另一个线程接收它
void put(E o);
//如果另一个线程当前正在使元素可用,则检索并删除此队列的头部
E poll();
//始终返回null
E peek();
//检索并删除此队列的头,如有必要,等待其他线程将其插入
E take();
//从此队列中删除所有可用的元素,并将它们添加到给定的集合中
int drainTo(Collection<? super E> c);
//始终返回false
boolean contains(Object o);
```
#### 2.8 LinkedBlockingDeque
LinkedBlockingDeque是双向链表实现的双向并发阻塞队列。**该阻塞队列同时支持FIFO和FILO两种操作方式**,即可以从队列的头和尾同时操作(插入/删除)并且该阻塞队列是支持线程安全。LinkedBlockingDeque还是**可选容量**的(防止过度膨胀)即可以指定队列的容量。如果不指定默认容量大小等于Integer.MAX\_VALUE。
  **定义一个LinkedBlockingDeque的方式有如下几种**
```java
//创建一个LinkedBlockingDeque队列初始容量为Integer.MAX_VALUE
LinkedBlockingDeque<String> queue = new LinkedBlockingDeque<String>();
//创建一个LinkedBlockingDeque队列设置初始容量
queue = new LinkedBlockingDeque<String>();
//设置初始容量为Integer.MAX_VALUE并且将其他类型的集合转为LinkedBlockingDeque队列
queue = new LinkedBlockingDeque<String>(new ArrayList<String>());
```
LinkedBlockingDeque有很多常用方法add、addFirst、、offer、put、poll、take、drainTo等关于其他方法可以查看API。
  **常用方法说明如下**
```java
//在此双端队列的末尾插入指定的元素,除非会违反容量限制
boolean add(E e);
//如果可以在不违反容量限制的情况下立即执行此操作则将指定的元素插入此双端队列的前面如果当前没有可用空间则抛出IllegalStateException
void addFirst(E e);
//如果可以立即执行此操作而不会违反容量限制则在此双端队列的末尾插入指定的元素如果当前没有可用空间则抛出IllegalStateException
void addLast(E e);
//如果可以在不违反容量限制的情况下立即执行操作则将指定的元素插入此双端队列表示的队列中换句话说在此双端队列的末尾如果成功则返回true如果当前没有可用空间则返回 false
boolean offer(E e);
//如果可以立即执行此操作而不会违反容量限制则在此双端队列的前面插入指定的元素如果成功则返回true如果当前没有可用空间则返回false
boolean offerFirst(E e);
//将指定的元素插入此双端队列的前面,如果空间足够,则需要等待指定的等待时间
boolean offerFirst(E e, long timeout, TimeUnit unit);
//如果可以立即执行此操作而不会违反容量限制则在此双端队列的末尾插入指定的元素如果成功则返回true如果当前没有可用空间则返回false
boolean offerLast(E e);
//将指定的元素插入此双端队列表示的队列中(换句话说,在此双端队列的末尾),如有必要,请等待空间变为可用
void put(E e);
//将指定的元素插入此双端队列的前面,如有必要,请等待空间变大
void putFirst(E e);
//将指定的元素插入此双端队列的末尾,如有必要,请等待空间变大
void putLast(E e);
//检索并删除此双端队列表示的队列的头部(换句话说,此双端队列的第一个元素),如果此双端队列为空,则返回 null
E poll();
//检索并删除此双端队列代表的队列的头部(换句话说,此双端队列的第一个元素),如果有必要使元素变为可用,则等待指定的等待时间
E poll(long timeout, TimeUnit unit);
//检索并删除此双端队列的第一个元素如果此双端队列为空则返回null
E pollFirst();
//检索并删除此双端队列的第一个元素,并在必要时等待指定的等待时间,以使元素变为可用
E pollFirst(long timeout, TimeUnit unit);
//检索并删除此双端队列的最后一个元素如果此双端队列为空则返回null
E pollLast();
//检索并删除此双端队列的最后一个元素,并在必要时等待指定的等待时间,以使元素变为可用
E pollLast(long timeout, TimeUnit unit);
//检索并删除此双端队列代表的队列的头部(换句话说,此双端队列的第一个元素),如有必要,请等待直到某个元素变为可用
E take();
//检索并删除此双端队列的第一个元素,如有必要,请等待直到元素可用
E takeFirst();
//检索并删除此双端队列的最后一个元素,如有必要,请等待直到元素可用
E takeLast();
//检索但不删除此双端队列代表的队列的头换句话说此双端队列的第一个元素如果此双端队列为空则返回null
E peek();
//检索但不删除此双端队列的第一个元素如果此双端队列为空则返回null
E peekFirst();
//检索但不删除此双端队列的最后一个元素如果此双端队列为空则返回null
E peekLast();
//检索但不删除此双端队列代表的队列的头
E element();
//检索但不删除此双端队列的第一个元素
E getFirst();
//检索但不删除此双端队列的最后一个元素
E getLast();
//检索并删除此双端队列代表的队列的头部
E remove();
//从此双端队列删除指定元素的第一次出现
boolean remove(Object o);
//检索并删除此双端队列的第一个元素
E removeFirst();
//从此双端队列删除指定元素的第一次出现
boolean removeFirstOccurrence(Object o);
//检索并删除此双端队列的最后一个元素
E removeLast();
//从此双端队列移除最后一次出现的指定元素
boolean removeLastOccurrence(Object o);
//从原子上删除此双端队列中的所有元素
void clear();
//从此队列中删除所有可用的元素,并将它们添加到给定的集合中
int drainTo(Collection<? super E> c);
//从此队列中最多移除给定数量的可用元素,并将它们添加到给定的集合中
int drainTo(Collection<? super E> c, int maxElements);
//从此双端队列表示的堆栈中弹出一个元素
E pop();
//将一个元素压入此双端队列表示的堆栈上
void push(E e);
//此双端队列是否包含指定的元素
boolean contains(Object o);
//返回此双端队列理想情况下(在没有内存或资源约束的情况下)可以接受而不会阻塞的其他元素的数量
int remainingCapacity();
//返回此双端队列的元素数量
int size();
```
#### 2.9 ArrayDeque数组双端队列
非阻塞、非线程安全、无边界数组双端队列当用作栈时性能优于Stack当用于队列时性能优于LinkedList
**定义一个ArrayDeque的方式有如下几种**
```java
public ArrayDeque() {
elements = (E[]) new Object[16]; // 默认的数组长度大小
}
public ArrayDeque(int numElements) {
allocateElements(numElements); // 需要的数组长度大小
}
public ArrayDeque(Collection<? extends E> c) {
allocateElements(c.size()); // 根据集合来分配数组大小
addAll(c); // 把集合中元素放到数组中
}
```
ArrayDeque有很多常用方法add、addFirst、、offer、put、poll、take、drainTo等关于其他方法可以查看API。
  **常用方法说明如下**
```java
//1.添加元素
addFirst(E e)//在数组前面添加元素
addLast(E e)//在数组后面添加元素
offerFirst(E e)// 在数组前面添加元素,并返回是否添加成功
offerLast(E e)// 在数组后天添加元素,并返回是否添加成功
//2.删除元素
removeFirst()//删除第一个元素,并返回删除元素的值,如果元素为null将抛出异常
pollFirst()//删除第一个元素并返回删除元素的值如果元素为null将返回null
removeLast()//删除最后一个元素并返回删除元素的值如果为null将抛出异常
pollLast()//删除最后一个元素并返回删除元素的值如果为null将返回null
removeFirstOccurrence(Object o) //删除第一次出现的指定元素
removeLastOccurrence(Object o) //删除最后一次出现的指定元素
//3.获取元素
getFirst() //获取第一个元素,如果没有将抛出异常
getLast() //获取最后一个元素,如果没有将抛出异常
//4.队列操作
add(E e) //在队列尾部添加一个元素
offer(E e) //在队列尾部添加一个元素,并返回是否成功
remove() //删除队列中第一个元素并返回该元素的值如果元素为null将抛出异常(其实底层调用的是removeFirst())
poll() //删除队列中第一个元素,并返回该元素的值,如果元素为null将返回null(其实调用的是pollFirst())
element() //获取第一个元素,如果没有将抛出异常
peek() //获取第一个元素如果返回null
//5.栈操作
push(E e) //栈顶添加一个元素
pop(E e) //移除栈顶元素,如果栈顶没有元素将抛出异常
//6.其他
size() //获取队列中元素个数
isEmpty() //判断队列是否为空
iterator() //迭代器,从前向后迭代
descendingIterator() //迭代器,从后向前迭代
contain(Object o) //判断队列中是否存在该元素
toArray() //转成数组
clear() //清空队列
clone() //克隆(复制)一个新的队列
```
### 3\. 链接地址
> https://www.liaoxuefeng.com/wiki/1252599548343744/1265122668445536
>
> https://www.cnblogs.com/bl123/p/13879243.html
>
> https://blog.csdn.net/truelove12358/article/details/106424619

View File

@ -0,0 +1,96 @@
Ubuntu mysql 8.0+安装
=====================
#### 1、下载MySQL配置文件网址https://dev.mysql.com/downloads/repo/apt/
##### 打开后将下拉到网页底部点击Download按钮下载deb文件
##### 进入下载页面选择No thanks, just start my download
#### 2、进入下载文件目录打开终端执行命令
```bash
sudo dpkg -i <下载的deb文件>
```
#### 3、接下来会弹出一个界面 设置好之后 选中ok按钮击Enter键进入下一步
##### 第一行 currently selectedmysql-8.0
##### 第二行 currently selectedEnabled
##### 第三行 默认
#### 4、执行更新命令
```bash
sudo apt update
```
#### 5、开始安装MySQL 8.0,执行命令
```
sudo apt install mysql-server
```
#### 6、接下来选择y继续
#### 7、设置root密码
#### 8、确认密码
#### 9、阅读配置MySQ社区服务器翻到末尾点使用Tab键选中ok按钮击Enter键
#### 10、加密方式选择Retain MySQL 5.x Compatibility
#### 11、完成
#### 启动mysql数据库
1、使用 service 启动service mysql start
2、使用 mysqld 脚本启动:/etc/inint.d/mysql start
3、使用 safe\_mysqld 启动safe\_mysql&
#### 设置远程连接
##### 1.登录mysql
`mysql -uroot -p`
##### 2.切换到mysql数据库
`use mysql;`
##### 3.修改host值所有地址都可以连接
`update user set host="%" where user="root";`
##### 4.刷新列表使其生效
`flush privileges;`
#### 重启
1、使用 service 启动service mysql restart
2、使用 mysqld 脚本启动:/etc/inint.d/mysql restart
#### 关闭
1、使用 service 启动service mysql stop
2、使用 mysqld 脚本启动:/etc/inint.d/mysql stop
3、 mysqladmin shutdown
#### 删除 MySQL
```bash
sudo apt-get autoremove mysql-server
```
#### 清理残留数据
```bash
dpkg -l |grep ^rc|awk '{print $2}' |sudo xargs dpkg -P
```

View File

@ -0,0 +1,124 @@
## mysql8.0 主从配置
### 一、主库master配置
#### 1、修改配置文件开启bin-log
```sh
#mysql8.0版本
vim /etc/mysql/mysql.conf.d/mysqld.cnf
#在mysqld.cnf最下面添加
#开启binlog 备份文件名称
log-bin = mysql-bin
#server-id在主从复制链路中服务id不能相同
server-id = 101
#不开启binlog的数据库
binlog-ignore-db=information_schema
binlog-ignore-db=sys
binlog-ignore-db=performance_schema
binlog-ignore-db=mysql
#只对一下数据库输出binlog 可以写多个不写则对所有未忽略的输出binlog
binlog-do-db = test
```
#### 2、创建master用户并且设置复制权限
```mysql
#创建用户 用户名可以随意命名访问地址设置从库ip
created user 'master'@'从库ip' identified with mysql_native_password by 'your password';
#赋予权限
grant replication slave on *.* to 'master'@'从库ip';
#刷新使刚才操作生效
flush privileges;
```
#### 3、查看配置是否生效
```mysql
#获取server_id 判断是否和配置文件中server_id相同
show variables like 'server_id';
#不相同则设置和配置文件相同
show variables like 'server_id';
#刷新后再次查看
flush privileges;
show variables like 'server_id';
#查看master配置 重启mysql服务生效 sudo service mysql resatrt;
show master status;
```
### 二、从库slave配置
#### 1、修改配置文件
```shell
#server-id 不能和主库相同
server-id=102
#忽略下方所有表操作
replicate_wild_ignore_table= information_schema.%
replicate_wild_ignore_table= sys.%
replicate_wild_ignore_table= performance_schema.%
replicate_wild_ignore_table= mysql.%
```
#### 2、设置主节点参数
```mysql
mysql> CHANGE MASTER TO
MASTER_HOST='主服务器id', -- 主库(master)IP
MASTER_USER='master', -- 主库(master)用户
MASTER_PASSWORD='123456', -- 主库(master)用户密码
MASTER_LOG_FILE='mysql-bin.000001', -- 主库(master)地址
MASTER_LOG_POS=856; -- 主库(master)位置 在主库中输入 show master status; 可以查看binlog地址 和 position位置
```
#### 3、查看配置是否生效
```mysql
#获取server_id 判断是否和配置文件中server_id相同
show variables like 'server_id';
#不相同则设置和配置文件相同
show variables like 'server_id';
#刷新后再次查看
flush privileges;
show variables like 'server_id';
```
#### 4、开启主从同步
```mysql
#开启主从
start slave;
#查看主从同步状态
show slave status\G;
#状态如下则表示同步成功
#Slave_IO_State: Waiting for source to send event
#Master_Host: 192.168.3.50
#Master_User: master50
#Slave_IO_Running: Yes
#Slave_SQL_Running: Yes
```
### 三、注意
#### 1、跨库操作不同补问题
我们在主库中添加了忽略库这里在mysql中 使用 database.table 进行跨库操作就会拦截跨库的操作所以建议不要使用跨库操作建议使用use database 切换操作库或者去掉主库忽略配置;
```mysql
use mysql;
delete test.user where id = 1
#因为所在库是mysqlmysql是我们的忽略库 他不会生成binlog 所以不会向从库同步
```
#### 2、从库不向主库同步
对从库进行操作不会对主库更新,如果想要从库向主库同步,将住服务器当从服务器,从服务器当主服务器,在执行一遍流程
#### 3、配置注意事项
(1) 主从服务器操作系统保持一致
(2) 主从数据库版本一致
(3) 主库开启bin-log主库和从库的server_id 唯一

File diff suppressed because it is too large Load Diff

199
proxy/FRP内网穿透.md Normal file
View File

@ -0,0 +1,199 @@
## FRP 内网穿透工具
- [[#FRP介绍|FRP介绍]]
- [[#环境准备|环境准备]]
- [[#[安装](https://github.com/fatedier/frp/releases)|[安装](https://github.com/fatedier/frp/releases)]]
- [[#配置SSH转发|配置SSH转发]]
- [[#服务端配置|服务端配置]]
- [[#客户端配置|客户端配置]]
- [[#测试链接|测试链接]]
- [[#注意事项|注意事项]]
- [[#配置http转发|配置http转发]]
- [[#服务端配置|服务端配置]]
- [[#客户端配置|客户端配置]]
- [[#测试|测试]]
- [[#多WEB服务配置|多WEB服务配置]]
- [[#根据域名来区分服务|根据域名来区分服务]]
- [[#服务端配置|服务端配置]]
- [[#客户端配置|客户端配置]]
- [[#测试|测试]]
- [[#根据端口来区分服务|根据端口来区分服务]]
- [[#服务端配置|服务端配置]]
- [[#客户端配置|客户端配置]]
- [[#测试|测试]]
### FRP介绍
frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。
### 环境准备
在开始之前我们需要准备的东西有一台需要做内网穿透的内网服务器 (后文称为客户端),一台可以访问外网的服务器(后文称为服务端)([阿里云](https://www.aliyun.com/?utm_medium=text&utm_source=bdbrand&utm_campaign=bdbrand&utm_content=se_32492)等) 以及一个已经备案并且别安服务器是服务端的域名(仅做 ssh 内网穿透不需要)。
### [安装](https://github.com/fatedier/frp/releases)
**下载后上传至服务器或者使用wget命令下载**
`wget [下载连接]`
>建议安装路径 /opt
**解压**
`tar -zxf ***`
**文件介绍**
+ frpc: 客户端启动程序
+ frpc_full.ini: 客户端所有配置项(可以再此文件查看 frp 的所有的配置项)
+ frpc.ini: 客户端配置项
+ frps: 服务端启动程序
+ frps_full.ini: 服务端所有配置项(可以再此文件查看 frp 的所有的配置项)
+ frps.ini: 服务端配置项
+ LICENSE: 许可证
### 配置SSH转发
##### 服务端配置
**编辑服务端配置文件**
```shell
#编辑服务端配置文件
vim frps.ini
#写入以下内容
[common]
bind_port = 7000 #用于和客户端连接通讯的端口
```
**服务端启动**
`./frps -c ./frps.ini`
> 这行命令的意思是以frps.ini的配置启动frps服务端
> 但是这样启动后退出就会中断服务
**使用nohup启动**
`nohup ./frps -c ./frps.ini &`
##### 客户端配置
**编辑编辑客户端配置文件**
```shell
#编辑客户端配置文件
vim frpc.ini
#写入以下内容
[common]
server_addr = 1.1.1.1 #服务端ip
server_port = 7000 #服务端bind_port的端口
[ssh]
type = tcp #连接类型
local_ip = 127.0.0.1 #本机的话则直接写入127.0.0.1 也可以是本机其他可ssh远程主机的ip
local_port = 22 #ssh端口默认为22
remote_port = 6000 #设置远程服务端对应的端口
```
**客户端启动**
`./frpc -c ./frpc.ini`
##### 测试链接
`ssh 服务端ip -p 6000`
##### 注意事项
+ 防火墙开启服务端端口7000、6000
+ 防火墙开启客户端端口22
### 配置http转发
##### 服务端配置
**编辑服务端配置文件**
```shell
#编辑服务端配置文件
vim frps.ini
#写入以下内容
[common]
bind_port = 7000 #用于和客户端连接通讯的端口
vhost_http_port = 8080 #访问服务端的8080端口frp会将http请求转发到客户端
```
**服务端启动**
`./frps -c ./frps.ini`
##### 客户端配置
**编辑客户端配置文件**
```shell
#编辑客户端配置文件
vim frpc.ini
#写入以下内容
[common]
server_addr = 1.1.1.1 #服务端ip
server_port = 7000 #服务端bind_port的端口
[web]
type = http #连接类型
local_ip = 192.168.3.5 #要转发web服务的ip地址本机的话可以省略这条 如果是其他web 写要进行转发的web服务的服务器ip
local_port = 80 #要转发web服务的端口
custom_domains = test.my.com #绑定域名 写多个则用,进行分割
```
**客户端启动**
`./frpc -c ./frpc.ini`
##### 测试
访问 http://test.my.com:8080
### 多WEB服务配置
#### 根据域名来区分服务
##### 服务端配置
**编辑服务端配置文件**
```shell
#编辑服务端配置文件
vim frps.ini
#写入以下内容
[common]
bind_port = 7000 #用于和客户端连接通讯的端口
vhost_http_port = 8080 #访问服务端的8080端口frp会将http请求转发到客户端
```
**服务端启动**
`./frps -c ./frps.ini`
##### 客户端配置
**编辑客户端配置文件**
```shell
#编辑客户端配置文件
vim frpc.ini
#写入以下内容
[common]
server_addr = 1.1.1.1 #服务端ip
server_port = 7000 #服务端bind_port的端口
[web]
type = http #连接类型
local_ip = 192.168.3.5 #要转发web服务的ip地址本机的话可以省略这条 如果是其他web 写要进行转发的web服务的服务器ip
local_port = 80 #要转发web服务的端口
custom_domains = test.my.com #绑定域名 写多个则用,进行分割
[web2] #保持唯一
type = http #连接类型
local_ip = 192.168.3.5 #要转发web服务的ip地址本机的话可以省略这条 如果是其他web 写要进行转发的web服务的服务器ip
local_port = 8080 #要转发web服务的端口
custom_domains = test2.my.com #绑定域名 写多个则用,进行分割
```
**客户端启动**
`./frpc -c ./frpc.ini`
##### 测试
访问 http://test.my.com:8080 => 192.168.3.5:80
访问 http://test2.my.com:8080 => 192.168.3.5:8080
#### 根据端口来区分服务
##### 服务端配置
**编辑服务端配置文件**
```shell
#编辑服务端配置文件
vim frps.ini
#写入以下内容
[common]
bind_port = 7000 #用于和客户端连接通讯的端口
```
**服务端启动**
`./frps -c ./frps.ini`
##### 客户端配置
**编辑客户端配置文件**
```shell
#编辑客户端配置文件
vim frpc.ini
#写入以下内容
[common]
server_addr = 1.1.1.1 #服务端ip
server_port = 7000 #服务端bind_port的端口
[web] #保持唯一
type = tcp #连接类型 注意这里不写http
local_ip = 192.168.3.5 #要转发web服务的ip地址本机的话可以省略这条 如果是其他web 写要进行转发的web服务的服务端ip
local_port = 80 #要转发web服务的端口
remote_port = 80 #访问服务器进行转发的端口
[web] #保持唯一
type = tcp #连接类型 注意这里不写http
local_ip = 192.168.3.5 #要转发web服务的ip地址本机的话可以省略这条 如果是其他web 写要进行转发的web服务的服务端ip
local_port = 8080 #要转发web服务的端口
remote_port = 8080 #访问服务器进行转发的端口
```
**客户端启动**
`./frpc -c ./frpc.ini`
##### 测试
访问 http://服务端ip:80 => 192.168.3.5:80
访问 http://服务端ip:8080 => 192.168.3.5:8080
[官方文档](https://gofrp.org/docs/)

View File

@ -0,0 +1,70 @@
Ubuntu install 花生壳
=====================
#### 一、下载花生壳deb安装文件
[内网映射\_穿透工具下载\_动态域名解析软件下载\_花生壳软件下载-贝锐花生壳 (oray.com)](https://hsk.oray.com/download/)
选择 Ubuntu Linux(X86\_64)之后点击下载
#### 二、将下载的deb文件上传至linux服务器
#### 三、开始安装
在deb文件同路径下输入下面命令开始安装
`sudo dpkg -i <deb文件全称>`
#### 四、浏览器登录
安装后会生成 SN码 以及默认登录密码admin
[登陆地址http://b.oary.com](http://b.oray.com)
账号输入自动生成的SN码 密码默认为admin
查看SN码命令
`sudo phddns status`
登陆上后可以绑定一个账号 以后登录使用SN码或者绑定的账号登录 密码为绑定账号的密码
#### 五、操作命令
##### 卸载
`dpkg -r phddns`
##### 启动
`phddns start`
##### 当前状态
`phddns status`
##### 停止
`phddns stop`
##### 重启
`phddns restart`
##### 重置
`phddns reset`
##### 开机自启动
`phddns enable`
##### 关闭开机自启动
`phddns disable`
##### 查看当前版本
`phddns version`
> 注意除phddns version命令不需要管理员权限外其他命令均需要管理员权限

View File

@ -0,0 +1,164 @@
MediaWiki搭建以及pivot皮肤配置
==============================
### 一、所需环境以及软件
#### 1、nginx v1.57+
#### 2、PHP v7.3.19 or v7.4.9+
#### 3、mysql v5.5.8+
#### 4、MediaWiki v1.36.1
#### 5、pivot v2.3.0
#### 6、php扩展
* ##### php-fpm
* ##### mbstring
* ##### xml
* ##### intl
* ##### mysql
### 二、安装nginx
```bash
sudo apt-get install nginx
```
### 三、安装PHP
#### 1、安装新版本PHP需要使用其他软件源
```bash
sudo apt install software-properties-common
sudo add-apt-repository ppa:ondrej/php
```
#### 2、进行安装
```bash
sudo apt install php7.4
php -v #查看版本
```
> 默认安装7.4版本中最新的版本 目前是7.4.21
#### 3、安装PHP扩展
```bash
sudo agt install php-fpm
sudo apt install php7.4-mbstring php7.4-xml php7.4-intl php7.4-mysql
```
### 四、配置MediaWiki
#### 1、下载压缩包上传至服务器[下载地址](https://www.mediawiki.org/wiki/Download)
#### 2、解压至任意路径
```bash
tar zxvf <压缩包>
```
#### 3、配置nginx进行代理
```bash
#进入nginx目录下
cd /etc/nginx
#打开配置文件
sudo vim nginx.conf
#更改第一行 user root; 后保存退出
user root;
#进入该文件夹
cd sites-available
#复制一份文件名称为wiki
sudo cp default wiki
#打开wiki
sudo vim wiki
#打开后删除里面所有内容后将一下内容添加进去
server {
listen <端口号> default_server;
listen [::]:<端口号> default_server;
root <wiki解压后的路径例/home/dev/software/MediaWiki/mediawiki-1.36.1;>
index index.html index.htm index.nginx-debian.html index.php;
server_name _;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
}
#注意修改端口号以及路径 修改完成后保存退出,跳转到以下路径
cd ../sites-enabled
#创建软连接
sudo ln -s /etc/nginx/sites-available/wiki wiki
#重启nginx 以及php7.4-fpm
sudo service nginx restart
sudo systemctl restart php7.4-fpm.service
```
#### 4、配置MediaWiki
* ##### 打开浏览器输入http://<安装wiki的服务器ip地址>:<在nginx配置的端口号>
* ##### 根据引导依次进行配置
* ##### 数据库选择mysql 填写数据库的地址,用户名,密码会自动初始化数据库
* ##### 设置wiki的名称以及管理员账号
* ##### 设置wiki用户权限皮肤编辑器等后
* ##### 点击继续进行安装安装时间较长有可能会出现504网关超时点击刷新继续提交
* ##### 完成后下载生成的LocalSettings.php文件 将其上传至服务器wiki的根目录index.php的同级目录中。
* ##### 进入MediaWiki http://<服务器ip>:<端口号>/index.php
### 五、配置pivot皮肤 [git地址](https://github.com/Hutchy68/pivot)
#### 1、下载皮肤包后进行解压修改名称为pivot [下载地址](https://github.com/hutchy68/pivot/archive/master.zip)。
#### 2、上传皮肤包到服务器wiki根目录下的skins目录中
#### 3、打开wiki根目录下的LocalSettings.php文件夹进行修改
```bash
$wgDefaultSkin = "pivot"; #指定为默认皮肤
wfLoadSkin( 'pivot' );
$wgPivotFeatures = array(
'showActionsForAnon' => true,
'fixedNavBar' => false,
'usePivotTabs' => false,
'showHelpUnderTools' => true,
'showRecentChangesUnderTools' => true,
'wikiName' => &$GLOBALS['wgSitename'],
'wikiNameDesktop' => &$GLOBALS['wgSitename'],
'navbarIcon' => false,
'preloadFontAwesome' => false,
'showFooterIcons' => true,
'addThisPUBID' => '',
'useAddThisShare' => '',
'useAddThisFollow' => ''
);
```
> ```
> 使用以下功能
> ```
>
> `LocalSettings.php`来更改行为。
>
> * `'showActionsForAnon' => true` 显示未登录访问者的页面操作。
> * `'fixedNavBar' => false`将允许导航栏随内容滚动,`true`将锁定导航栏。
> * `'usePivotTabs' => false` 设置为 true 以在 wiki 页面中启用 Foundation 选项卡标记。
> * `'showHelpUnderTools' => true` 将在“工具”下创建指向“帮助”的链接。
> * `'showRecentChangesUnderTool's => true` 将在“工具”下创建指向“最近更改”的链接。
> * `'wikiName' => &$GLOBALS['wgSitename']`默认是站点名称。设置为在不更改系统 wikiname 的情况下显示简短版本。
> * `'wikiNameDesktop' => &$GLOBALS['wgSitename']`默认站点名称。设置为在桌面视图中显示更长的名称。
> * `'navbarIcon' => false`移动视图中没有图标,`true`以使用 wiki 的全局设置徽标路径图像。
> * `'preloadFontAwesome' => false`设置为 true 以将 Font Awesome 预加载为 `<head>`元素。有助于克服未正确设置的 MIME 类型服务器配置。
> * `'showFooterIcons' => false`将显示文本代替页脚图标,`true`将输出全局设置的图标。
> * `'addThisPUBID' => ''`空字符串不会触发 AddThis 脚本,`'ra-##-#######'`发布者 ID 将仅允许在内容页面上异步运行 AddThis 脚本。
> * `'useAddThisShare' => ''`默认空字符串,不使用 AddThis 共享,`your_addthis_specific_div_class_string`将直接在页面标题下插入共享工具箱 div但在带有自定义 div 类的标语之前。
> * `'useAddThisFollow' => ''`默认为空字符串,不使用 AddThis follow`your_addthis_specific_div_class_string`将使用 `right-footer`自定义 div 类在图标或文本输出之前的区域中插入关注工具箱 div 。
#### 4、皮肤配置完成用户登录后可以在个人中心来选择要使用的皮肤

View File

@ -0,0 +1,32 @@
### Ubuntu netplan 网络配置
+ ##### 找到配置文件
```shell
cd /etc/netplan
sudo vim ***-config.yaml
```
+ ##### 配置netplan
```shell
配置如下:
network:
ethernets:
enp4s0: #网卡名称 我这里默认是enp4s0
addresses: [192.168.0.20/24] #IP地址
gateway4: 192.168.0.1 # 网关
nameservers:
addresses: [114.114.114.114, 192.168.0.1] #DNS
dhcp4: no
optional: no
version: 2
```
+ ##### 启用生效
```shell
sudo netplan apply
```

View File

@ -0,0 +1,29 @@
Ubuntu20.04 设置开机自启
========================
### 第一步
执行 **ls /lib/systemd/system** 你可以看到有很多启动脚本,其中就有我们需要的 **rc-local.service**
### 第二步
打开 **rc-local.service**脚本内容,内容如下:
一般正常的启动文件主要分成三部分
* \[Unit\] 段: 启动顺序与依赖关系
* \[Service\] 段: 启动行为,如何启动,启动类型
* \[Install\] 段: 定义如何安装这个配置文件,即怎样做到开机启动
* 可以看出,/etc/rc.local 的启动顺序是在网络后面,但是显然它少了 Install 段,也就没有定义如何做到开机启动,所以显然这样配置是无效的。 因此我们就需要在后面帮他加上 \[Install\] 段:
————————————————
版权声明本文为CSDN博主「任求其-zzx」的原创文章遵循CC 4.0 BY-SA版权协议转载请附上原文出处链接及本声明。
原文链接https://blog.csdn.net/qq\_43685040/article/details/111574332
### 第三步
### 第四步
### 第五步
### 第六步

35
ubuntu/开机自启动.md Normal file
View File

@ -0,0 +1,35 @@
**1 添加 systemd 配置文件:**
`vim /usr/lib/systemd/system/myservice.service`
文件内容如下:
```
[Unit]
Description=My Test App
After=syslog.target
[Service]
ExecStart=/opt/test/test.sh
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
```
>ExecStart表示服务执行的命令可以直接是shell命令也可以是shell脚本这里以shell脚本为例
>Restart 如果设置为on-failure则当进程以非零退出代码退出由信号终止当操作(例如服务重新加载)超时,以及何时触发配置的监视程序超时时,将重新启动服务。
>RestartSec 等待5秒然后启动服务。
**2. 设置开机启动**
```shell
# 刷新服务列表
systemctl daemon-reload
# 设置开机自启
systemctl enable myservice
# 设置开机关闭
systemctl disable myservice
# 启动服务
systemctl start myservice
# 关闭服务
systemctl stop myservice
# 查看服务状态
systemctl status myservice
```

View File

@ -0,0 +1,52 @@
### 一、为root账户设置ssh密钥登录
**1、进入 root 用户,进入 / root**
```shell
su root
cd /root
```
**2、新建文件夹**
`mkdir /root/.ssh`
**3、生成密钥密钥会自动保存在 / root/.ssh 目录里。**
`ssh-keygen -t rsa`
再连摁三下回车
**4、进入. ssh 文件夹里面有两个文件id_rsa 是私钥需要自己下载到本地id_rsa.pub 是公钥,该名成 authorizedkeys**
```shell
cd /root/.ssh
mv id_rsa.pub authorized_kyes
```
**5、设置文件和文件夹权限**
```shell
chmod 600 /root/.ssh/authorized_keys
chmod 700 /root/.ssh
```
**6、修改 / etc/ssh/sshd_config 文件,并重启服务**
`vim /etc/ssh/sshd_config`
修改下面两项
```
PasswordAuthentication: no // 禁止使用基于口令认证的方式登陆
PubkeyAuthentication: yes // 允许使用基于密钥认证的方式登陆
```
重启ssh服务使配置生效
`service sshd restart`
之后登录时选择密钥Publickey登录导入生成的私钥id_rsa。
### 二、为普通账户设置ssh密钥登录
在要设置的账户目录下进行上面的2-6操作 例cd /home/user