0%

H5手机端日志工具(vconsole手机端):

1
2
3
4
5
6
<script src="https://cdn.bootcdn.net/ajax/libs/vConsole/3.15.1/vconsole.min.js"></script>
<script>
// 初始化 vConsole
var vConsole = new VConsole();
console.log('vConsole is ready.');
</script>

第一种情况:传数据给原生端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
if (window.webkit != undefined) {
//这是ios端定义的
window.webkit.messageHandlers.getUserInfo.postMessage(null);
} else {
//这是android端定义的feedback
feedback.getUserInfo();
}

if (window.webkit != undefined) {
window.webkit.messageHandlers.feedback.postMessage({
title: "测试分享的标题",
content: "测试分享的内容",
url: "https://github.com/maying1992",
});
} else {
// try {
// result = feedback.getUserInfo();
// } catch(err){
// }
feedback.postMessage();
}

第二种情况:获取原生端的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
created() {
//window挂载
window.setUserInfo = this.setUserInfo;
},

setUserInfo(param) {
const u = navigator.userAgent;
const isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
const result = JSON.parse(param);
if (isiOS) {

this.queryParams = result.userInfo.token;

//兼容原生端那边传过来的不统一值
if (
result.userInfo.userId == undefined ||
result.userInfo.userId == 0
) {
this.usrIdd = 0;
} else {
this.usrIdd = result.userInfo.userId;
}

window.localStorage.setItem("lang", result.userInfo.language);

} else {
this.queryParams = result;
if (result.userId == undefined || result.userId == 0) {
this.usrIdd = 0;
} else {
this.usrIdd = result.userId;
}
window.localStorage.setItem("lang", result.language);

}
this.$i18n.locale = localStorage.getItem("lang");
// let data = {
// 'name' : 'xiaoming'
// };
return localStorage.getItem("lang");
}

当需要通过按钮跳转到app时:

直接用 a 标签的 href 跳转,前提是原生应用定义了 myapp://*** 作为触发特定功能的URL,可参考 Instagram 的 H5 跳转 app 的竞品例子,instagram://**
一般跳不过去就是原生端不支持。

JavaScript 基础总结(变量提升、严格模式)


变量与函数提升规则

  • 变量提升:按顺序执行,变量声明提升但赋值不会提升。
  • 函数提升:整个函数体提升到全局作用域顶部。
  • 优先级:函数提升 > 变量提升。
1
2
3
4
5
6
7
console.log(a); // undefined
var a = 2;

foo(); // 正常调用
function foo() {
console.log("函数提升成功");
}

使用 use strict 严格模式

作用:

  • 避免创建意外的全局变量
  • 禁止使用未声明变量,防止内存泄漏;
  • this 默认绑定到 undefined 而非 window
1
2
3
4
5
6
7
function foo() {
"use strict";
console.log(this.a); // ❌ TypeError
}

var a = 2;
foo(); // 严格模式下 this 是 undefined,无法读取 this.a

1
2
3
4
5
6
7
8
9
10
(function() {
"use strict";
foo(); // 严格模式下调用函数则不影响默认绑定
})();

function foo() {
console.log(this.a);
}

var a = 2;

1. 登录广东政务服务网申请毕业生接收

  • 打开 广东政务服务网
  • 搜索“人才引进” → 选择“接收毕业生”
  • 填写个人资料后,下载电子版《申请书》

2. 报到证改派

  • 每个地区流程略有不同,建议致电报到证抬头地区的人社局咨询
  • 示例:汕尾市城区 → 在广东政务服务网搜索“档案转出” → 点击在线办理
  • 上传报到证、申请表等资料到“调函”栏目
  • 不久后,工作人员会联系确认是否需要电子版“同意改派”文件(推荐选择电子版), 她会把电子版的“同意改派”发到我们填的邮箱里。

其他地区如潮州市:可直接在广东政务服务网搜索“报到证改派”在线办理

3. 上传材料至“广东就业创业”小程序

  • 打开小程序,选择应届生接收模块
  • 上传材料:电子版“同意改派”的报到证、申请表、三方协议等
  • 等待校方审核通过

4. 返回广东政务服务网上传最终材料

  • 上传审核通过后的报到证等资料
  • 审核通过后会收到含有“指标卡”的短信通知

5. 在“深圳本地宝”预约现场办理

  • 打开“深圳本地宝”微信公众号,搜索“大学生”
  • 进入现场办理流程 → 点击“户政预约” → 选择“普通户政预约”
  • 预约业务选择“接收应届生户籍迁入”
  • 选择时间和地点并预约成功后,带好上述资料和以下材料前往办理:
    • 户口本
    • 身份证及二代回执
    • 一寸白底照片

6. 第一次现场办理后领取档案袋

  • 办理后工作人员会发放档案袋
  • 需在五个工作日后再次前往办理

7. 第二次预约并完成迁户手续

  • 提前预约,带齐上次材料再次前往办理
  • 办理成功后可选择身份证邮寄

备注: 整个流程较为繁琐,建议提前准备资料并留意预约时间。

《遇见未知的自己》读书笔记

何为“未知”?

“自己”即指“真我”,从“我是谁”到后来的“从有到无”,整本书以若菱与一位智者老人的对话为主线,引申出许多深刻的生命观念。


核心观点

  • 外面没有别人,只有你自己。
    所有的外境,其实都是内心的投射。

  • 与潜意识对话的黄金时刻
    想象自己已经实现目标的最佳时刻,是清晨将醒未醒、夜晚将睡未睡之间的那段时间,因为那时我们最接近潜意识。

  • 关键修炼:觉察、臣服、战胜胜肽(小我)

    • 觉察:关注当下的自己,不批判地观察情绪和反应。
    • 臣服:接受现实,而不是抗拒。
    • 胜肽小我:代表恐惧、比较、焦虑的内在声音,要学会看见并超越它。

  • 冥想、感恩、付出

    • 冥想时,要设想自己已经拥有渴望的生活。
    • 在实现之前就先学会感恩。
    • 保持利他、愿意付出的心态。

  • 少关心别人,多关心自己

    • 注意力回到自己身上,关注内在世界。
    • 当情绪上来时,觉察身体哪个部位最不舒服,了解内在信号。

总结

这本书不只是关于“找到自己是谁”,更是提醒我们“成为那个自己”。内在力量的唤醒,需要持续的觉察、练习与自我超越。

《当我谈跑步时,我谈些什么》

也就是看了这本书,才知道世界上会有另一个自己在做着自己喜欢的事情。看这本书之前,从没有看过村上君写的书。知道有这么一个火人,也知道那么多火书,但就是没怎么看过。可论及跑步呀,觉得能与之有所交流。一直跑下去,会不会就到月球上了呢?跑步并非为了长命百岁,而是在有限生命里让自己活得更轻松点罢了。

惊喜于能发现村上君跑步时的想象力,天马行空我很喜欢,我也曾幻想过很多,也会跑着跑着就突然想起一句歌词,什么现在加快速度追幸福呀 blala……长跑需要耐力,但没有想象力可不行哟。当然前提是热爱跑步,一个不喜欢跑步的人,你说再多也无动于衷;一个热爱跑步的人,即使是雨天,也想要在停雨空隙去相遇另一个自己。人本孤独,但精神却能得到共鸣。

想着未来一定会坚持跑下去,不管世界如何变化。自从有次在外一整天走了 30 公里,除了身体上晒伤的疼痛以外,我更喜欢的是精神世界的富足。没经历过,就没有话语权。可能我跟陈坤一样,是个悲观的极乐主义者,在世上积极活着,却也看透红尘。不以物喜,不以己悲。脉搏也降到一分钟 50 多次,看来还是很适合慢跑的。说这么多,主要还是兴趣使然。只要不限制我的自由,一切好说。

想着来年,我也会参加马拉松,然后旁边的人都在为我加油,那该有多 happy。

“我不是人,是一架纯粹的机器,所以什么也无须感觉,唯有向前奔跑。”

极为像的一点就是我们都喜欢不停地奔跑,不是那种觉得自己快不行了就走几步,也不是适当的时候停下来看风景。可能每个人的见解不同。但我觉得能不停跑下去的人才是真正的王者。

当抵达终点那一刻,会觉得怎么那么酷,一股自豪感涌上来,就好比中了彩票或是走了狗屎运。这是原则,亦是我的骄傲。

噢对,好比尚三哥在终点等着我,然后我得意地笑了。

阿太

阿太倔强坚强,豁达的心态值得人学习。父亲最强大的地方就是娶了我的母亲。一个伟大的女人。真正的女人就是应该要积极乐观面对一切,用自己的双手打造自己想要的未来。

虽然有偷窃,但也是生活所迫,为了生存,为了家人,放下面子干一些违心事,又何尝不是一种积极的心态呢?而不是一哭二闹三上吊。

想来作者能有如此作为,跟他伟大的母亲脱不了干系。

那可爱的母亲呀!为了父亲的面子,为了父亲开心,都坚持要把房子建完,这何尝不是一种力量,向往心之所向,佩服这种勇气。

其实最了解父亲的人是母亲,母亲知道父亲好面子,爱情不就是这样吗?你不用说,我懂,我懂你懂我,所以我们才会在一起这么久。

张美丽

从哪里跌倒,就从哪里爬起来。仿佛看见一个追求真爱,为爱为自己想要的东西不懈努力的人,虽说最终还是被迫性解放了自己,但她曾经的所作所为仍让我敬佩。

舆论的力量是强大的,但比其而言,张美丽的内心力量更强大。

全书的确包含了很多他自己的“偏见”,但我觉得他真实幽默,语言简单易懂,其实各个小标题就是告诉我们该做什么。

懂生活

生活从来不是你想怎样就能变成怎样的。生活中多发现美,多从他人角度看待事情,是好的。同时自己还要有自知之明。

懂爱情

谢耳朵说:人穷尽一生追寻另一个人类共度一生的事,我一直无法理解。或许我自己太有意思,无需他人陪伴。所以我祝你们在对方身上得到的快乐,与我给自己的一样多。
靠另一个人永远无法让你摆脱孤独,只能靠自己对生活的热情。经营一段感情要的是理智,自由是不可剥夺的。这让我想起对前任,我曾经有查看过他的手机,我觉得挺不对,以后不会再出现这种事情了。

懂兵法

主要就是介绍女追男或男追女的技巧,以及如何经营好一段感情,就是大智慧。同时千万别因为家庭放弃自己的事业,不要跟公公婆婆住一起(但我的观点还是觉得因人而异),要有属于自己的兴趣爱好。

懂婚姻

忍,忠一。对于不婚主义,当然也没什么想多说的了。

懂失意

每一次失恋,只不过是在为真爱让路。还是那句勉强不来,我爱你,所以我祝你一生如意,即使陪着你的人,不是我。
做自己想做的事,不要管他人怎么想。只关心自己在乎的人。

懂阅读

What Why How。一直阅读下去,不要求快,要求精。

懂情趣

介绍了他与妻子的日常 sweet,告诉我们不分手,就不知道世界上还有那么多人值得我们去爱。如果找到了,是我的幸运,如果找不到,我也有能力让自己快乐地活着。
高情商地活着,会发觉世界是那么美好。

懂交际

跟正经人交往,跟不同人要有不同方式去与之交往,拒绝别人也是一门艺术。如果没有厚脸皮去找别人还钱,干脆别借。

懂人性

只能说我可能在人性方面持怀疑态度,管不了别人,那么就只能管好自己,别做个恶俗的人。

懂善恶

有些人在你生命中出现,就是为了给你上一课。何为善何为恶,我宁愿相信他人的话,因为人与人之间的信任本来就是有一方愿意相信,另一方才会不负此信。
即使被骗,也是告诉我们下次同样的坑,别再跳了。但别因为入了一次坑,就不再相信了,善人始终存在。
上帝让右手成为右手,就是对右手最高的奖赏;同理,上帝让善人成为善人,也就是对善人的最高奖赏。
这让我想起,有次在外,洗手间里没有纸巾,原本是想问旁边的好朋友有没有纸巾的,结果旁边一位陌生女子听见了,立刻拿出包纸巾给我,此等善举,让我倍感荣幸。
而善良还需要有原则,否则害人害己。

懂财富

穷人之所以穷,是思维的匮乏。要想富起来,不能只在自己身体上投资,而要在大局上有思维的开拓。看透问题的本质。
时间是有限,在有限时间内如何快速致富?找到一门自己感兴趣的学科,学以致用,发散思维,与社会息息相关的行业,去做。

懂社会

要有抱负,一步一个脚印。要有自己独立的人格,要能为自己所做的事情负责。学会转化一种让自己幸福的能力,然后改变自己。

懂生死

生死学里几个词:无死不生,向死而生,知死而后生。颇为有趣且发人深思。人就是因为知道有一天会死去,才会争取好好地活着。
我想,真到了那天,我会主动拥抱死亡。

这世界上缺的不是完美的人,而是从心底给出的正义、真心、无畏和同情—这是今天看完《无问西东》后给我最感慨的话。生而为人,便要心之所向,无问西东。
大家都知道有因必有果,却不只因果皆由缘而起。叔本华跟尼采,有时间必好好读佳作。

懂远游

这部分写了琢磨先生在西藏的经历,看过很多书,都是大家想去西藏的。也许去了那里,人真的能体会到人生的不易。
美国不如英国自律,日本对美食态度极佳,常把“对不起”挂在嘴边,不喜欢给别人添麻烦。

懂职场

首先要懂得吃苦,然后要清楚自己,发掘自己的天赋所在。以终为始,聚焦所做。

懂教育

我只知道,每一个出生在这世上的小孩都是纯粹的,如果不好好教育,长大后便不可能为国之栋梁。

懂娱乐、懂自由

人生有两个方向:一个方向是往大处拼搏,保持对事业的激情;一个方向是往小处生活,保持做人的温度。
每天睁开眼,对自己说声:欧耶

var、let、const 三者的区别?

✅ 作用域

  1. var 定义的变量没有块作用域,可以跨块访问,但不能跨函数访问
  2. let 定义的变量有块作用域,只能在声明的代码块中访问
  3. const 定义的是常量,必须初始化,只能在声明的代码块中访问,且值不可更改

✅ 声明规则

  • 同一个变量名,只能用一种声明方式,否则会报错。

✅ 结合 this 的区别

特性 var / let / const
改变 this 指向 ✅ 可以
第一个参数是 this 要指向的对象 ✅ 是
没传对象或为 undefined/null 默认指向全局 window
参数传递 apply 用数组,call 用参数列表,bind 可多次传参
执行方式 apply/call 立即执行,bind 返回新函数
什么是事件委托?
  • 事件委托,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,而不是目标元素
  • 当事件响应到目标元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数
防抖跟节流的区别是什么?
  • 防抖:只执行最后一次。事件持续触发,但只有等事件停止触发后 n 秒后才执行函数。
  • 节流:控制执行频率。持续触发,每 n 秒执行一次函数。
Web 前端预防 SQL 注入的方法有哪些?
  1. 参数化查询:使用预处理语句或参数化查询来避免 SQL 注入。
  2. 验证用户输入:验证用户输入的数据,确保其符合预期格式,避免非法字符等。
  3. 转义特殊字符:在使用用户输入的数据构造 SQL 语句时,对特殊字符进行转义,以防止注入。
  4. 限制权限:限制用户的权限,使其不能执行不安全的 SQL 操作。
  5. 白名单验证:白名单验证是指确保用户输入的数据只能是允许的值,避免非法数据的输入。
  6. 审核代码:定期审核代码,以确保代码的安全性,特别是对于数据库连接和查询部分的代码。
http 和 https 的区别
  1. https 协议需要到 ca 申请证书,一般免费证书较少,因而需要一定费用。
  2. http 是超文本传输协议,信息是明文传输,https 则是具有安全性的 ssl 加密传输协议。
  3. http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
  4. http 的连接很简单,是无状态的;HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 http 协议安全。
created跟mounted的区别
  • created发生在mounted之前,此时DOM元素还没完全渲染出来,不过跟后端联调时候的请求可以放在这里,尽早获取到数据返回给变量。
  • mounted这时候已经可以获取页面中的DOM元素了。
说说事件循环机制

🔁 什么是事件循环?

JavaScript 是单线程语言,执行代码时除了依赖调用栈,还依赖任务队列来控制异步代码的执行顺序。

整个执行过程称为 事件循环(Event Loop)

🧠 事件循环的核心概念:

  • 一个线程中只有一个事件循环(主循环)。
  • 可以有多个任务队列,按类型分为:
    • 宏任务(Macro Task)
    • 微任务(Micro Task)

⏱ 执行顺序是怎样的?

执行顺序:

宏任务 ➝ 微任务(清空) ➝ 下一个宏任务 ➝ 微任务(清空)… 依此循环

  1. 执行一个宏任务(如 script 整体代码)
  2. 在当前宏任务中执行所有产生的微任务
  3. 若微任务中又产生新的微任务,继续执行,直到清空微任务队列
  4. 开始下一轮宏任务循环

🧩 宏任务(Macro Task)有哪些?

  • script(整体代码)
  • setTimeout
  • setInterval
  • setImmediate(Node.js)
  • I/O 操作
  • UI 渲染

🧬 微任务(Micro Task)有哪些?

  • process.nextTick(Node.js 专属,优先级更高)
  • Promise.then / catch / finally
  • async / await
  • MutationObserver
说说 css 盒模型

css 中的盒子模型包括 IE 盒子模型和标准的 W3C 盒子模型

在标准的盒子模型中,width 指 content 部分的宽度,box-sizing:content-box(默认为content-box);

在 IE 盒子模型中,width 指的是 content+padding+border,box-sizing:border-box;

Box-sizing:padding-box 宽度包含了左右 padding+width

vue2 和 vue3 的区别
  1. 双向数据绑定原理不同,vue2 使用 Es5 的 API defineProperty()对数据进行劫持, 只能监听某个属性,不能对整个对象监听;vue3 使用 ES6 的 proxy API 对数据代理, 可以监听整个对象和数组
  2. 生命周期不同
    vue2:beforeCreate、created 、beforeMount、mounted、beforeUpdate、updated、
    beforeDestroy、destroyed
    vue3:setup 、onBeforeMount 、 onMounted 、onBeforeUpdate 、onUpdated 、
    onBeforeUnmount、onUnmounted
  3. vue2 必须有根标签,vue3 可以没有根标签,会默认将多个根标签包裹在 fragment虚拟标签中
  4. vue2 采用选项式 API,将函数和数据统一起来处理,将功能点切割了,当逻辑复杂时不利于代码阅读;vue3 采用组合式 API,将同一个功能的代码统一起来处理,使代码更有序,有利于代码的书写和维护
  5. vue2 和 vue3 匿名插槽不一样
    具名插槽使用方式不同:vue2 使用 slot=’’,vue3 使用 v-slot:’’
    作用域插槽使用方式不同:vue2 中在父组件中使用 slot-scope=”data”从子组件获取数据,vue3 中在父组件中使用 #data 或者 #default=”{data}”获取

目录

redis-token缓存
jwt跟redis存token的区别
redis相关知识
推荐

redis-token缓存

  • redis.js创建

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    const redis = require("redis");

    // Redis 链接的配置内容
    const client = redis.createClient({
    socket: {
    host: '192.168.64.2', // Redis 服务器地址
    port: 6379, // Redis 端口
    },
    password: '123456' // Redis 密码
    });

    // 连接到 Redis
    client.connect()
    .then(() => {
    console.log('Connected to Redis');
    })
    .catch((err) => {
    console.error('Redis connection failed:', err);
    });

    // 处理连接错误
    client.on("error", (err) => {
    console.error('Redis error:', err);
    });

    // 定义 Redis 操作方法
    const redisOps = {
    // 创建值
    set: async (key, value, expiration = null) => {
    try {
    value = JSON.stringify(value);
    if (Number.isInteger(expiration) && expiration > 0) {
    // 如果设置了有效时间并且是整数,使用 SETEX 命令
    await client.setEx(key, expiration, value);
    } else {
    // 否则直接使用 SET 命令
    await client.set(key, value);
    }
    console.log(`Key "${key}" set successfully with expiration: ${expiration || 'no expiration'}`);
    } catch (err) {
    console.error('Error setting value:', err);
    }
    },

    // 删除值
    del: async (key) => {
    try {
    await client.del(key);
    console.log(`Key "${key}" deleted successfully`);
    } catch (err) {
    console.error('Error deleting key:', err);
    }
    },

    // 获取值
    get: async (key) => {
    const result = await client.get(key);
    console.log('99999=', result)
    try {
    return result; // 尝试解析为 JSON
    } catch (error) {
    // 如果不是 JSON 格式,直接返回原始值
    console.warn(`Warning: Value for key "${key}" is not JSON formatted.`);
    return result;
    }
    },

    // 获取键的 TTL
    ttl: async (key) => {
    try {
    const timeLeft = await client.ttl(key);
    console.log(`Key "${key}" has TTL: ${timeLeft}`);
    return timeLeft;
    } catch (err) {
    console.error('Error getting TTL:', err);
    return err;
    }
    },
    };

    module.exports = redisOps;

  • redis的使用

1
2
3
4
5
6
const redisOps = require("./redis.js");
const moment = require('moment-timezone');

let token = jwt.sign({ id: user.userid, username: user.username }, secretKey, { expiresIn: '1h' });

await redisOps.set(user.userid.toString(), token, 60 * 60)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//token校验
const verifyToken = async (ctx, next) => {
const userid = ctx.headers['cookie'];
const match = userid.match(/userid=(\d+)/);
const userId = match ? match[1] : null;

if (!userId) {
ctx.status = 401;
console.log('No token provided');
ctx.body = { message: 'No token provided' };
return;
}

try {
const startTime = moment(); // 记录开始时间
const getuserid = await redisOps.get(userId)
const endTime = moment(); // 记录结束时间
const duration = moment.duration(endTime.diff(startTime)); // 计算持续时间

console.log(`Request completed in ${duration.asMilliseconds()} ms`); // 以毫秒为单位输出耗时
if(getuserid){
await next();
}else {
throw err;
}

} catch (err) {
console.log('Token verification failed:', err.message);
ctx.status = 401;
ctx.body = { message: 'Failed to authenticate token' };
}
};

jwt跟redis存token的区别

维度 JWT Redis
性能 - 无需查询数据库或访问外部存储,验证速度较快
- 适用于简单的身份验证场景
- 需要与 Redis 服务器进行通信,可能会有网络延迟
- 适用于复杂的会话管理和存储需求

redis相关知识

  • redis本质上是一个key-value类型的内存数据库,性能最快的key-value数据库。

  • 正常情况是把数据存储在数据库 ,数据库把数据存在磁盘。但越上层的存储器存储效率越高,内存位于磁盘之上。而redis是一款基于内存的存储系统,数据都存在内存里,所以从redis读取数据会比从数据库读取要快。

  • 内存有限,存储不了太多数据。出现故障时,用主从复制、哨兵法。集群就是一套完整的redis多机解决方案。他有效解决了单机redis的所有问题。当你在集群中为某个节点配置从机的时候,主从节点间同步就是主从复制。主节点挂掉之后,从节点的选取,内部逻辑与哨兵机制相似。

  • 支持发布/订阅模式,可以作为一个简单而高效的轻量级消息代理,用于实现消息队列、实时通知等。

使用 Docker 安装 ELK Stack(ElasticSearch、Logstash、Kibana)

建议在 Docker 上安装,资源占用少。以下安装版本统一为 8.12.2,建议保持一致避免冲突。

目录

1、安装 ElasticSearch
2、安装 Logstash
3、安装 Kibana
推荐


1、安装 ElasticSearch

  • 拉取镜像:
1
docker pull elasticsearch:8.12.2
  • 启动容器:
1
docker run --name some-elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -d elasticsearch:8.12.2
  • 进入容器内部:
1
sudo docker exec -u 0 -it some-elasticsearch bash
  • 重启容器:
1
docker restart some-elasticsearch

2、安装 Logstash

  • 拉取镜像:
1
docker pull docker.elastic.co/logstash/logstash:8.12.2
  • 启动容器:
1
sudo docker run -it -p 5044:5044 -p 9600:9600 --name logstash -v /usr/share/logstash/piplines:/usr/share/logstash/config --privileged=true docker.elastic.co/logstash/logstash:8.12.2 /bin/bash
  • 使用 scp 命令将本机下载好的 jar 包(MySQL Connector)上传至虚拟机:
1
scp "/Users/Downloads/logstash-8.12.2/mysql-connector-j-8.4.0.jar" 用户名@虚拟机IP:/home
  • 再将 jar 包从虚拟机移动到 logstash 容器中:
1
docker cp ./mysql-connector-j-8.4.0.jar logstash:/usr/share/logstash
  • 进入容器内部:
1
docker exec -u 0 -it logstash bash

3、安装 Kibana

  • 拉取镜像:
1
docker pull kibana:8.12.2
  • 启动容器:
1
docker run --name some-kibana -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -d elasticsearch:8.12.2
  • 进入容器:
1
docker exec -u 0 -it some-kibana bash

附:安装 Docker、Portainer 及相关命令

1
2
3
4
5
6
7
8
9
10
11
12
sudo apt update
sudo apt install docker.io docker-compose
docker -v
sudo systemctl start docker

sudo docker search portainer
docker pull portainer/portainer
sudo docker pull portainer/portainer
sudo docker run -d --name portainerUI -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer

sudo docker start portainerUI
sudo passwd root