docs: 迁移笔记

This commit is contained in:
yuany3721 2026-04-02 23:12:36 +08:00
parent aede6f5d87
commit bf16e96bab
131 changed files with 5959 additions and 0 deletions

View File

@ -0,0 +1,6 @@
import { defineClientConfig } from 'vuepress/client'
export default defineClientConfig({
// 客户端配置
// 可以在这里添加全局组件、样式等
})

View File

@ -0,0 +1,37 @@
import { viteBundler } from '@vuepress/bundler-vite'
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'
export default defineUserConfig({
base: '/',
lang: 'zh-CN',
title: 'vuepress-yuany3721',
head: [
// 配置站点图标
['link', { rel: 'icon', type: 'image/png', href: 'logo.png' }],
],
bundler: viteBundler(),
shouldPrefetch: false,
theme: plumeTheme({
hostname: 'https://blog.yuany3721.site/',
autoFrontmatter: {
permalink: false,
createTime: true,
title: true,
},
contributors: false,
readingTime: false,
markdown: {
image: {
figure: true,
lazyload: true,
},
},
}),
})

View File

@ -0,0 +1,81 @@
import { defineThemeConfig } from 'vuepress-theme-plume'
/**
* @see https://theme-plume.vuejs.press/config/basic/
*/
export default defineThemeConfig({
logo: 'logo.png',
appearance: true, // 配置 深色模式
navbar: [
{ text: '首页', link: '/' },
{ text: '随记', link: '/notes/' },
{ text: '文档', link: '/doc/AD9910/AD9910' },
{ text: '归档', items: [{ text: '笔记', link: '/笔记/' }] },
{ text: '更新日志', link: '/updatelog/Web/Web' },
{ text: '友链', link: '/friends/' },
],
collections: [
{
type: 'post',
dir: 'blog',
title: '博客',
link: '/blog/',
},
{
type: 'post',
dir: 'notes',
title: '随记',
link: '/notes/',
},
{
type: 'doc',
dir: '笔记',
title: '笔记',
sidebar: 'auto',
sidebarCollapsed: true,
},
{
type: 'doc',
dir: 'categories',
title: '杂谈',
},
{
type: 'doc',
dir: 'doc',
title: '文档',
linkPrefix: '/doc/',
sidebar: [
{ prefix: 'AD9910', items: ['AD9910'] },
{ prefix: 'glm3', items: ['GLM3'] },
],
},
{
type: 'doc',
dir: 'updatelog',
title: '更新日志',
linkPrefix: '/updatelog/',
sidebar: [
{ prefix: 'Bot', items: ['Bot', '21.08.20前累积更新日志'] },
{
prefix: 'Web',
items: [
'Web',
'23.05.01前累积更新日志',
'22.05.16前累积更新日志',
'21.08.16前累积更新日志',
],
},
],
},
],
footer: {
// message: "",
copyright:
'<a href=\'http://www.beian.miit.gov.cn/\'>鄂ICP备2022017895号-1</a> | <a href=\'http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=42011102005054\'>鄂公网安备 42011102005054号</a>',
},
prevPage: false,
nextPage: false,
createTime: 'only-posts',
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

View File

@ -0,0 +1,119 @@
import requests
import json
def test_server(url: str = "http://127.0.0.1:56789/test/"):
"""
测试服务端连通性
:param url: test URL
:return: 返回True为正常False为异常
"""
response = requests.get(url)
return response.status_code == 200 and json.loads(response.text)["res"] == 1
def get_server(message: str, url: str = "http://127.0.0.1:56789/ctr/"):
"""
发送命令
:param message: message to send
:param url: URL to send to
:return: 返回True为正常False为异常
"""
data = {
"text": message
}
json_data = json.dumps(data)
headers = {
"Content-Type": "application/json"
}
response = requests.post(url, data=json_data, headers=headers)
return response.status_code == 200 and json.loads(response.text)["res"] == message
def post_server(message: str, url: str = "http://127.0.0.1:56789/ctr/"):
"""
发送命令
:param message: message to send
:param url: URL to send to
:return: 返回True为正常False为异常
"""
data = {
"text": message
}
json_data = json.dumps(data)
headers = {
"Content-Type": "application/json"
}
response = requests.post(url, data=json_data, headers=headers)
if response.status_code == 200:
return json.loads(response.text)
else:
return {"error": "status code: " + str(response.status_code)}
def get_time_seq() -> list[str]:
"""
获取时间序列
:return time_seq: list[str]
:str日期格式为"2024-01-23 01:23:45.123456"
:dict: 检查"message"字段是否为"ok"如果是则存在"data"字段为长度范围在10~1000的list如果长度不足10"message"字段会返回当前长度信息示例{'message': 'now queue size 1'}这时不存在"data"字段
"""
data = post_server(message="SYS:TIME:GET?")
if "error" in data:
return {"message": data["error"]}
data = json.loads(data)
return {
"message": "ok",
"data": data
}
def clr_time_seq() -> None:
"""
清空时间序列
"""
return get_server(message="SYS:TIME:CLR")
def curve_start() -> None:
"""
扫频一级触发信号
"""
return get_server(message="SYS:CURVE:START")
def curve_stop() -> None:
"""
扫频结束信号立即结束扫频
"""
return get_server(message="SYS:CURVE:STOP")
def reset_brd() -> None:
"""
软件重置AD9910
"""
return get_server(message="SYS:RESET")
if __name__ == "__main__":
# print(test_server())
# print(curve_start())
# print(curve_stop())
# print(reset_brd())
'''
res = get_time_seq()
if res["message"] == "ok":
print(len(res["data"]))
print(res["data"])
else:
print(res)
'''
print(clr_time_seq())

View File

@ -0,0 +1,137 @@
from fastapi import FastAPI
from pydantic import BaseModel
from datetime import datetime
import uvicorn
import threading
from queue import Queue
import json
import serial
import serial.tools.list_ports
class BoundedQueue(Queue):
def __init__(self, maxsize):
super().__init__(maxsize)
self._maxsize = maxsize
def put(self, item) -> None:
if self.qsize() < self._maxsize:
super().put(item)
else:
self.get()
super().put(item)
def get_all(self) -> list[str]:
elements = []
while not self.empty():
elements.append(self.get())
return elements
def clr(self) -> None:
while not self.empty():
self.get()
def send_to_stm32(device, string: str) -> None:
for _ in range(10):
# print(datetime.now(), "S")
device.write(string.encode("utf-8"))
def read_from_stm32(device, queue: BoundedQueue) -> None:
while True:
if device.in_waiting:
data = device.read(device.in_waiting).decode()
# print("Received:", data)
if "SYS:TRIG" in data:
queue.put(str(datetime.now()))
def get_time_seq(queue: BoundedQueue) -> list[str]:
if not queue.empty():
return queue.get_all()
else:
return []
def clear_time_seq(queue: BoundedQueue) -> None:
queue.clr()
class Item(BaseModel):
text: str
app = FastAPI()
@app.get("/test/")
async def test():
return {"res": 1}
@app.post("/ctr/")
async def ctr(message: Item):
global buffered_queue
data = message.text
print(datetime.now(), 'receive msg:', data)
if data == "SYS:CURVE:START":
# 开始扫频曲线
send_thread = threading.Thread(target=send_to_stm32, args=(stm32, data))
send_thread.start()
return {"res": message.text}
elif data == "SYS:CURVE:STOP":
# 结束扫频曲线
send_thread = threading.Thread(target=send_to_stm32, args=(stm32, data))
send_thread.start()
return {"res": message.text}
elif data == "SYS:RESET":
# 结束扫频曲线
send_thread = threading.Thread(target=send_to_stm32, args=(stm32, data))
send_thread.start()
return {"res": message.text}
elif data == "SYS:TIME:GET?":
# 获取时间序列
if buffered_queue.empty() or buffered_queue.qsize() < 10:
return {"error": "now queue size " + str(buffered_queue.qsize())}
else:
return json.dumps(get_time_seq(buffered_queue))
elif data == "SYS:TIME:CLR":
# 清除时间序列
clear_time_seq(buffered_queue)
return {"res": message.text}
def run_server():
"""
Starts the web server using uvicorn.
This function is only intended to be called from the if __name__ == "__main__": block.
It will not return until the web server is stopped.
:return None:
"""
uvicorn.run(app, host="127.0.0.1", port=56789)
buffered_queue = BoundedQueue(maxsize=1000)
if __name__ == "__main__":
for port in serial.tools.list_ports.comports():
if "STM" in port.description:
portname = port.device
break
else:
print("未找到设备")
exit()
with serial.Serial(portname, 115200) as stm32:
read_thread = threading.Thread(target=read_from_stm32, args=(stm32, buffered_queue))
server_thread = threading.Thread(target=run_server)
server_thread.start()
read_thread.start()
read_thread.join()

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,5 @@
---
pageLayout: home
config:
- type: posts
---

View File

@ -0,0 +1,171 @@
---
title: Centos7 / Windows10配置frp+远程桌面
createTime: 2021/08/29
tags:
- Centos
- Windows
categories:
- blog
---
##
> frp 由客户端(frpc)和服务端(frps)组成,服务端通常部署在具有公网 IP 的机器上,客户端通常部署在需要穿透的内网服务所在的机器上。 内网服务由于没有公网 IP不能被非局域网内的其他用户访问。用户通过访问服务端的 frps由 frp 负责根据请求的端口或其他信息将请求路由到对应的内网机器,从而实现通信。 在 frp 中一个代理对应一个需要暴露的内网服务。一个客户端支持同时配置多个代理。 \
> [官方文档](https://gofrp.org/docs)
### 代理类型
| 类型 | 描述 |
| ------ | ---------------------------------------------------------------------------------------- |
| tcp | 单纯的 TCP 端口映射,服务端会根据不同的端口路由到不同的内网服务。 |
| udp | 单纯的 UDP 端口映射,服务端会根据不同的端口路由到不同的内网服务。 |
| http | 针对 HTTP 应用定制了一些额外的功能,例如修改 Host Header增加鉴权。 |
| https | 针对 HTTPS 应用定制了一些额外的功能。 |
| stcp | 安全的 TCP 内网代理,需要在被访问者和访问者的机器上都部署 frpc不需要在服务端暴露端口。 |
| sudp | 安全的 UDP 内网代理,需要在被访问者和访问者的机器上都部署 frpc不需要在服务端暴露端口。 |
| xtcp | 点对点内网穿透代理,功能同 stcp但是流量不需要经过服务器中转。 |
| tcpmux | 支持服务端 TCP 端口的多路复用,通过同一个端口访问不同的内网服务。 |
## 配置 Centos 服务端
```bash
# 下载Latest Release
wget https://github.com/fatedier/frp/releases/LatestRelease/frp.tar.gz
# 解压
tar -zxf frp.tar.gz
# 进入解压后的文件夹
cd frp
# 配置服务端配置文件
vi frps.ini
```
```ini
; 配置基本内容
[common]
bind_port = 7000
; frp自带的frps控制台
dashboard_port = 7001
dashboard_user = xxxx
dashboard_pwd = xxxx
```
```bash
# 启动frps
./frps -c frps.ini
```
## 配置 Windows 客户端
下载 Latest Release for Windows amd64 并解压 编辑 frpc.ini
```ini
[common]
server_addr = 1.2.3.4
server_port = 7000 ; frpc中的
[remote_desktop]
type = tcp
local_ip = 127.0.0.1
local_port = 3389 ; Windows远程桌面的默认端口
remote_port = 8011
```
进入 cmd`./frpc.exe -c frpc.ini`这时使用另一台电脑运行`mstsc`,连接`1.2.3.4:8011`并输入凭据即可顺利登录到 Windows 远程桌面
### 检查可能的问题:
1. Windows 未开启远程桌面
2. Windows 未开启远程访问权限(系统--远程设置--允许远程连接至此电脑)
3. 远程桌面的其他设置(系统--远程桌面)
4. 查看设置的端口是否被占用对应端口防火墙是否打开frpc 是否与 frps 端口对应bind_port 是 frp 提供服务的端口local_port 是客户端需要访问的服务所在端口remote_port 是访问客户端服务的服务端端口)
## 设置 Window10 的 frpc 开机自启
新建`run.bat`
```powershell
# 使用绝对路径
D:\frp_0.37.0\./frpc.exe -c D:\frp_0.37.0\frpc.ini > D:\frp_0.37.0\frpc.log
```
新建`frpc.bat`
```vb
@ECHO OFF
%1 start mshta vbscript:createobject("wscript.shell").run("""%~0"" ::",0)(window.close)&&exit
start /b run.bat
' 这里的run.bat也需要用绝对路径
```
`frpc.bat`放到`C:\Users\用户名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup`里即可
## 关于 xtcp
- 开防火墙 udp
```bash
firewall-cmd --permanent --add-port=7002/udp --zone=public
firewall-cmd --reload
```
- 修改`frps.ini`
```ini
[common]
bind_port = 7000
bind_udp_port = 7001
dashboard_port = 7001
dashboard_user = xxxx
dashboard_pwd = xxxx
```
- 配置 frpc1需要被访问的服务所在主机`frpc.ini`
```ini
[common]
server_addr = 1.2.3.4
server_port = 7000
[remote_desktop]
type = tcp
local_ip = 127.0.0.1
local_port = 3389
remote_port = 8011
[xtcp_remote_desktop]
type = xtcp
sk = abcdefg
local_ip = 127.0.0.1
local_port = 3389
```
- 配置 frpc2访问服务的主机`frpc.ini`
```ini
[common]
server_addr = 1.2.3.4
server_port = 7000
[xtcp_visitor]
type = xtcp
role = visitor
server_name = xtcp_remote_desktop ; 与上面的对应
sk = abcdefg
bind_addr = 127.0.0.1
bind_port = 1234
```
- 启动两个 frpc都正常注册访问 127.0.0.1:1234 进行连接时两个 frpc 同时报错:
```bash
[xtcp_remote_desktop] get sid from visitor error: read udp 192.168.1.101:57484: i/o timeout
[xtcp_visitor] get sid from visitor error: read udp 192.168.1.104:60475->103.98.240.96:42221: i/o timeout
```
截至 Aug 30 2021 GMT+08[GitHub issue](https://github.com/fatedier/frp/issues)中对此问题的回答仍然是与运营商 NAT 机制有关,无法稳定穿透,请尝试 stcp\_\
## 用 nginx 伪装端口
nginx 的 stream 没有`server_name`选项,所以即使拿域名伪装后面也会带一个端口号
~~以及安装 nginx 的时候并没有`--with-stream`,所以懒得弄了= =~~

View File

@ -0,0 +1,557 @@
---
title: 一次基于LXD的实验室GPU服务器环境配置及踩坑记录
createTime: 2023/07/17 17:36:48
tags:
- Ubuntu
- LXD
categories:
- blog
---
[[toc]]
## 前言
本文的受众为实验室的公用 GPU 服务器管理员,需要有一定的 Linux 基础,或者对此感兴趣的普通用户。
如果您并不关心为何这样配置服务器环境,以及对如何部署、管理这样一台服务器不感兴趣,可以选择跳过这些内容,前往[管理员指北](./2023-06-23.md#管理员指北)、[用户指南](./2023-06-23.md#用户指南)。
事情的起因是实验室购入了一台公用 GPU 服务器,考虑到每个人所需的软件和环境差异巨大,因此,需要一种方案来满足多用户对服务器的使用的需求。
这里列出一些期望达到的目标:
- 不同用户之间不能相互影响
- 用户要能便捷地访问服务器
- 用户的操作不能影响到宿主机的稳定运行
- 用户应当可以自由地访问外部网络
- 用户应当可以使用 GPU不同用户可以共享 GPU
- 用户应当可以自由地配置程序运行环境
- 管理员应该能轻松地管理用户
**注意:** _本次部署属于科研基础架构的部署属于各种软件的工程实现和部署本身并不具备科研价值同样也无法基于该方法搭建的服务器实验运行结果、实验数据产出做出任何保障。_
## 架构选择
从最初的需求出发,我们想要不同用户之间不能相互影响,也就是在用户级别进行隔离,主流的隔离方案包括 Docker容器化、LXCLinux 容器、OpenVZ虚拟机
首先是容器方案,以 Docker 为例。考虑到开销问题Ubuntu in Docker 首先被排除备选。Docker 有成熟的[NVIDIA-Docker](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#container-runtimes)支持,可以允许不同容器之间共享 GPUDocker 成熟的网络接口也使容器的可访问性得到了保障,同时可以使用 Linux 内核的[cgroups](https://manpages.ubuntu.com/manpages/focal/en/man7/cgroups.7.html)灵活分配硬件资源,是一个不错的备选方案。
OpenVZ、KVM、Xen 等虚拟机方案在资源利用上不够轻量,管理上相较 Docker 也复杂很多,同样基于开销问题将其排除备选。
LXC 可以理解为内核级的容器,允许不同容器之间共享 GPU相比 Docker 更加轻量,也可以更方便地使用系统资源。
Docker 的隔离更偏向于运行环境的隔离,将应用和全部依赖环境全部打包到一个单一对象中,可以在不包含完整的操作系统的情况下运行应用,而 LXC 基于 namespaces 进行隔离,可以用**更低的开销**提供灵活的系统环境,支持用户在系统层面肆意整活,这给了我充足的理由选择 LXC。**甚至**用户可以在 LXC 容器中再套娃一个 Docker既然如此也没什么好纠结的了。
> **什么?你问 LXD**
> 那只是我用原生 LXC 觉得太麻烦,并且解决了 LXC 支持跨主机容器迁移不完全、容器管理复杂等问题的备胎,不提也罢(×)。
> by yuany3721
<br/>
::: details 如果您对 LXC 与 LXD 的区别感兴趣,您可以展开这里了解一些信息
<p>就在本次部署的两周前LXD 于 2023 年 6 月 4 日正式移交给 Canonical<a href="https://linuxcontainers.org/lxd/#project-announcement">公告</a>中展示了这一动作的具体变化。</p>
<p>就使用体验而言LXD 无疑是远超 LXC 的,尽管它们似乎(可能就是)用的同一种实现方式和内核。</p>
<p>以下是一些功能在使用上的区别,也正是复杂性的问题,使我放弃了直接使用 LXC 的想法,转而由 LXD 实现本次部署。</p>
| 功能 | LXC | LXD |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
| 新建容器 | `lxc-create -t download -n template -- --dist ubuntu --release jammy --arch amd64` | `lxc launch tuna-images:ubuntu/jammy template` |
| 启动容器 | `lxc-start -n template` | `lxc start template` |
| 向容器中注入命令 | `lxc-attach -n template -- apt update` | `lxc exec template -- apt update` |
| 修改容器配置 | `vi path/to/lxc/template/config` | `lxc config edit template` |
| 挂载 GPU | `for x in $(ls /dev/nvidia\*); do echo lxc.mount.entry = $x $(echo $x \| cut -b 2-) none bind,optional,create=file >> path/to/lxc/template/config done` | `lxc config device add template gpu gpu` |
<p>上述举例如果不能使您窥见一斑,您可以尝试参照<a href="https://linuxcontainers.org/lxc/manpages/">LXC 文档</a><a href="https://documentation.ubuntu.com/lxd/en/latest/">LXD 文档</a>进行尝试。</p>
:::
<br/>
## 环境说明及前置工作
### **环境说明**
本次的物理机硬件环境如下:
```text
CPU: Intel(R) Xeon(R) Platinum 8336C CPU
RAM: Samsung DDR4 SingleBitECC 3200 MT/s * 4
GPU: NVIDIA GeForce RTX 4090 * 2
Disk: Samsung SSD 980 1TB + WUH721816AL 14TB
```
宿主机所在网络环境如下:
```text
gateway: 172.16.60.1/23
mask: 255.255.254.0
```
### **前置工作**
1. 安装 Ubuntu Server
选择 Ubuntu Server 22.04.2 作为宿主机的系统,使用 rufus 制作系统启动盘后插入服务器,使用 SuperMicroIPMIView 扫描 IPMI 端口,连接 IPMI 服务安装系统,细节省略。
_这里其实可以通过网络安装 ubuntu但是没有折腾mark 一下以后有机会进行尝试_
2. 配置系统环境
参考[Ubuntu Server 基本环境配置](../note/linux/2023-06-20.md)
- 配置系统联网超时
- 配置 swap 分区
- 配置数据盘挂载
`WUH721816AL 14TB`格式化为`/dev/sda1`,并挂载在`/data`目录
设置 data 目录权限:
```bash
$ sudo chmod 755 /data
$ sudo chmod +t /data
```
- 配置 OpenSSH可选
允许密码登录、修改服务端口为 33
- 配置防火墙
参考[ufw 防火墙配置](../note/linux/2021-09-28.md)
```bash
$ sudo ufw allow 33/tcp
$ sudo ufw enable
$ sudo ufw reload
```
3. 配置网桥
在类似我们的方案中,[为实验室建立公用 GPU 服务器](https://abcdabcd987.com/setup-shared-gpu-server-for-labs/)、[实验室 GPU 服务器的 LXD 虚拟化](https://github.com/shenuiuin/LXD_GPU_SERVER)等实操中(不知道为什么)采用了基于 iptables、端口映射的技术实现绕过宿主机访问容器。
**但是!这一点也不优雅!** 服务器就在内网,又不缺 IPv4 地址为何要加上端口号访问呢因此我在宿主机中建立了一个网桥lxc 容器通过网桥直接从网关 DHCP 获取 IP。
在 Ubuntu22.04 中,系统默认使用 netplan 配置网络。我们直接以修改 netplan 配置的方式新建一个网桥:
```bash
$ cd /etc/netplan
# 备份默认配置
$ sudo cp 00-installer-config.yaml 00-eno1-br0-bridge.yaml
$ sudo mv 00-installer-config.yaml 00-installer-config.yaml.bak
$ sudo vi 00-eno1-br0-bridge.yaml
network:
renderer: networkd
ethernets:
eno1:
# 固定IP
dhcp4: no
bridges:
br0:
interfaces: [eno1]
# 这是修改网桥之前eno1网卡获取到的ip保持一致可以避免一些麻烦
addresses: [172.16.61.82/23]
routes:
# 配置默认网关gateway4已经被标记为deprecated不建议使用
- to: default
via: 172.16.60.1
# 加上权重不进行配置的话产生冲突使用route命令查看路由表会看到eno1和br0两条default路由导致无法联网
metric: 100
nameservers:
addresses:
# DNS服务器edit as you like
- 114.114.114.114
- 8.8.8.8
- 8.8.4.4
version: 2
# 应用网络
$ sudo netplan try
```
检查网络配置,`ip a`类似这样:
> 2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br0 state UP group default qlen 1000\
> link/ether 3c:ec:ef:cc:60:28 brd ff:ff:ff:ff:ff:ff\
> altname enp6s0\
> 5: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000\
> link/ether d6:87:d1:44:19:7c brd ff:ff:ff:ff:ff:ff\
> inet 172.16.61.82/23 brd 172.16.61.255 scope global br0\
> valid_lft forever preferred_lft forever\
> inet6 fe80::d487:d1ff:fe44:197c/64 scope link\
> valid_lft forever preferred_lft forever
`route`类似这样:
> Kernel IP routing table\
> Destination&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Gateway&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Genmask&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Flags&nbsp;Metric&nbsp;Ref&nbsp;&nbsp;&nbsp;&nbsp;Use&nbsp;Iface\
> default&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_gateway&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.0.0.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UG&nbsp;&nbsp;&nbsp;&nbsp;100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;br0\
> 172.16.60.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.0.0.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;255.255.254.0&nbsp;&nbsp;&nbsp;U&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;br0
## 配置 LXD-GPU 环境
### **配置运行环境**
1. 安装 LXC、LXD
这里的 LXD 使用`5.0/stable`版本,请使用前先查阅[LXD 官方安装指引](https://documentation.ubuntu.com/lxd/en/latest/installing/#how-to-install-lxd)修改安装版本号。
```bash
$ sudo apt update
$ sudo apt install lxc
$ sudo snap instll lxd --channel=5.0/stable
```
如果需要的话,可能有必要进行[apt 换源](../note/linux/2023-01-10.md)
由于 snap 只有 server outside the Great Firewall所以提示`Unable to contact snap store`的时候,可能需要一点点科学上网手段,以下是临时设置 snap 代理的方法:
```bash
$ sudo snap set system proxy.http="your proxy url"
$ sudo snap set system proxy.https="your proxy url"
```
2. 检查 lxc 的依赖
使用`lxc-checkconfig`检查 lxc 容器的必要组件。具体到本次配置,该命令显示系统存在以下问题:
```text
Cgroup v1 systemd controller: missing
Cgroup v1 freezer controller: missing
Cgroup ns_cgroup: required
```
在 Ubuntu22.04 中,默认情况下不会启用 cgroup v1 systemd controller 和 ns_cgroup。编辑`/etc/default/grub`
```text
GRUB_CMDLINE_LINUX="cgroup_enable=memory systemd.unified_cgroup_hierarchy=0 cgroup_namespace.enable=1"
```
保存并退出后,更新 GRUB 配置并重新启动系统以应用修改。
```bash
$ sudo update-grub
$ sudo reboot
```
3. 配置防火墙以适应网桥
在 Ubuntu22.04大概率以及未来的版本ufw 改变了它的默认规则,需要修改网桥的 route 属性,否则会导致 lxc 容器无法从外部网关获取 IP即使正确地配置了 daemon、dhcp 等所有服务。参考[Ubuntu 22.04 LXD networking issue, not getting IPs, and solution](https://discuss.linuxcontainers.org/t/ubuntu-22-04-lxd-networking-issue-not-getting-ips-and-solution-please-verify-correctness/14739)
```bash
$ sudo ufw allow out on br0
$ sudo ufw route allow out on br0
```
### **配置基础镜像**
_注以下配置过程中`$`开头表示命令在宿主机中运行,`root@template:~#`开头表示命令在 template 容器中以 root 身份exec 进去的运行。_
1. 初始化 LXD 环境
```bash
$ lxd init
```
以下是我的配置选项,仅供参考:
```text
Would you like to use LXD clustering? (yes/no) [default=no]: no
Do you want to configure a new storage pool? (yes/no) [default=yes]:
Name of the new storage pool [default=default]: lxd-pool
Name of the storage backend to use (cephobject, dir, lvm, zfs, btrfs, ceph) [default=zfs]:
Create a new ZFS pool? (yes/no) [default=yes]:
Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) [default=no]:
Size in GiB of the new loop device (1GiB minimum) [default=30GiB]: 50GiB
Would you like to connect to a MAAS server? (yes/no) [default=no]:
Would you like to create a new local network bridge? (yes/no) [default=yes]: no
Would you like to configure LXD to use an existing bridge or host interface? (yes/no) [default=no]: yes
Name of the existing bridge or host interface: br0
Would you like the LXD server to be available over the network? (yes/no) [default=no]:
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]:
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]: yes
config: {}
networks: []
storage_pools:
- config:
size: 50GiB
description: ""
name: lxd-pool
driver: zfs
profiles:
- config: {}
description: ""
devices:
eth0:
name: eth0
nictype: bridged
parent: br0
type: nic
root:
path: /
pool: lxd-pool
type: disk
name: default
projects: []
cluster: null
```
修改默认配置文件,限制默认存储大小,避免一个容器占满硬盘
```bash
$ lxc profile edit default
config: {}
description: Default LXD profile
devices:
eth0:
name: eth0
nictype: bridged
parent: br0
type: nic
root:
path: /
pool: lxd-pool
size: 50GB
type: disk
name: default
used_by: []
```
2. 创建基础容器模板
添加清华 LXC 镜像,创建`template`容器模板
```bash
$ lxc remote add tuna-images https://mirrors.tuna.tsinghua.edu.cn/lxc-images/ --protocol=simplestreams --public
$ lxc launch tuna-images:ubuntu/jammy template
Creating template
Starting template
```
配置基本环境
```bash
# 进入容器
$ lxc exec template bash
# 修改默认用户的密码
root@template:~# passwd ubuntu
yourpassword
# 修改时区
root@template:~# timedatectl set-timezone Asia/Shanghai
# 修改apt源
root@template:~# cp /etc/apt/sources.list /etc/apt/sources.list.bak
root@template:~# vi /etc/apt/sources.list
# 注释掉源码部分加快apt update速度
deb https://mirrors.ustc.edu.cn/ubuntu/ jammy main restricted universe multiverse
deb https://mirrors.ustc.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse
deb https://mirrors.ustc.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse
deb https://mirrors.ustc.edu.cn/ubuntu/ jammy-security main restricted universe multiverse
deb https://mirrors.ustc.edu.cn/ubuntu/ jammy-proposed main restricted universe multiverse
# deb-src https://mirrors.ustc.edu.cn/ubuntu/ jammy main restricted universe multiverse
# deb-src https://mirrors.ustc.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse
# deb-src https://mirrors.ustc.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse
# deb-src https://mirrors.ustc.edu.cn/ubuntu/ jammy-security main restricted universe multiverse
# deb-src https://mirrors.ustc.edu.cn/ubuntu/ jammy-proposed main restricted universe multiverse
root@template:~# apt update
root@template:~# apt upgrade -y
# 安装ssh server
root@template:~# apt install -y openssh-server
# 安装必要软件
root@template:~# apt install -y ufw net-tools
```
3. 配置 GPU 环境
```bash
# 挂载gpu
$ lxc config device add ContainerName gpu gpu
# 查看显卡设备文件
$ ls /dev/nvidia*
# 安装显卡驱动
root@template:~# apt install -y ubuntu-drivers-common
root@template:~# ubuntu-drivers devices
root@template:~# ubuntu-drivers autoinstall
root@template:~# nvidia-smi
# 禁用自动更新(23.08.11update)
root@template:~# apt-mark hold *nvidia*
root@template:~# apt-mark showhold
# 显卡驱动版本
dpkg -l | grep nvidia
# NVRM版本
cat /proc/driver/nvidia/version
```
出现类似以下界面说明显卡驱动配置成功。
![nvsmi](./img/nvsmi.png)
4. 发布`template`作为基础容器模板
```bash
$ lxc stop template
$ lxc publish template --alias template --public
```
5. 基于`template`建立带桌面环境的容器模板
```bash
$ lxc launch template template-gnome
$ lxc exec template-gnome
# 安装gnome桌面
root@template-gnome:~# apt install --no-install-recommends -y ubuntu-desktop
# 安装xrdp远程
root@template-gnome:~# apt install -y xrdp
root@template-gnome:~# systemctl enable xrdp
```
发布`template-gnome`
```bash
$ lxc stop template-gnome
$ lxc publish template-gnome --alias template-gnome --public
```
**至此,本次服务器的环境部署就完成了,以下为管理员与用户的使用说明。**
## 管理员指北
**注意:** 宿主机的权限对您是完全开放的,如果您需要在宿主机中执行任何本节之外的命令,请您执行前务必完全明确您的操作会带来什么后果。
### **如何访问宿主机**
您有两种连接宿主机的方式:
1. 使用 ssh 工具访问**宿主机 IP 的 33 端口**,并使用**用户名**和**密码**进行认证;
2. 在浏览器中访问**宿主机的 IPMI 端口 IP**,并使用**IPMI 用户名**和**IPMI 密码**进行认证,进入“远程控制”选项卡,启动控制台。
这两种方法的区别在于ssh 访问的是 Ubuntu 系统,您只能在系统级别对宿主机进行控制,使用 IPMI 访问则可以获得宿主机包括 BIOS、硬件在内的完全控制。**如非必要,不建议访问 IPMI 端口进行管理**
### **新建容器**
当前已经配置好了`template``template-gnome``template-docker`三种容器模板,分别代表最基础的命令行容器、带 gnome 桌面和 xrdp 远程的容器、带 docker 环境的命令行容器,推荐用户使用`template`进行操作。
以用户提供的容器名为`yuany3721`为例,以下操作可以为该用户新建一个容器:
```bash
# 新建容器
$ lxc launch template-docker yuany3721
# 挂载GPU
$ lxc config device add yuany3721 gpu gpu
# 挂载硬盘
$ sudo mkdir /data/yuany3721/
$ sudo chown -R 1000:1000 /data/yuany3721
$ lxc config device add yuany3721 data disk source=/data/yuany3721/ path=/data/
$ lxc config device add yuany3721 sdata disk source=/data/share/ path=/sdata/
# 查看容器详情
$ lxc list
```
然后将查看到的容器 IPeth0告知用户用户即可使用`ssh ubuntu@container-IP`访问容器。
如果用户需要在容器中使用 docker需要额外修改容器配置如下
```bash
$ lxc config set yuany3721 security.nesting true
$ lxc config set yuany3721 security.privileged true
$ lxc restart yuany3721
```
### **删除容器**
```bash
$ lxc stop delcontainer
$ lxc delete delcontainer
```
## 用户指南
### **联系管理员获取授权**
您需要告知管理员的信息包括:您的用户名、您是否需要图形界面(推荐无图形界面,性能更好)、您是否希望使用 docker
管理员会告知您一个 IP您可以通过该 IP 访问服务器,身份认证的账号为`ubuntu`,密码为`123456`
**注意:** 访问服务器的账号与您的用户名**无关** ;您在获取授权后请尽快访问服务器并**修改密码**
默认情况下,数据卷将被挂载于`/data`(用户目录)和`/sdata`(共享目录),共享目录的`/sdata/model`中有常用模型文件。
### **从命令行访问服务器并修改密码**
Ubuntu 在输入密码时不会显示输入内容,请不要惊慌,正常输入完毕回车即可。
以 Windows 系统为例,<kbd>Win+R</kbd>打开`cmd`,输入命令`ssh ubuntu@您的IP`,访问服务器。
提示以下信息时,输入 yes 回车,然后输入默认密码`123456`
```text
The authenticity of host '172.16.61.xx (172.16.61.xx)' can't be established.
xxxx key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxx/s.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
```
![connect2lxc](./img/connect2lxc.png)
在新出现的命令行中输入`passwd ubuntu`修改密码,修改成功后就可以使用新的密码登录服务器了。
![passwd](./img/passwd.png)
### **通过 xrdp 登录图形界面**
在 Windows 下,可以使用系统自带的 RDP 软件,<kbd>Win+R</kbd>打开`mstsc`,输入管理员给您的 IP点击连接若出现提示称无法验证远程计算机身份忽略提示并点击“是”继续连接
![winRDP](./img/winRDP.png)
连接后出现以下界面,在界面中输入账号`ubuntu`密码为默认密码或您修改过的密码点击“OK”如果信息无误则可以正常连接到服务器。
![xrdp](./img/xrdp.png)
如果您不是 Windows 机器Linux 可安装 remmina 访问Mac 可安装 Microsoft Remote Desktop 访问,操作类似,在此不再赘述。
该连接方式的优点是可以获得完整的 Linux 桌面体验,但当网络环境不佳时操作延时特别大、桌面长时间运行可能会卡死。
### **文件传输**
系统配置了一个端口为 22 的 sftp 服务器,您可以使用 Filezilla 等 ftp 工具连接并使用 ftp 进行文件传输。
当然,您也可以通过远程桌面进行文件拖放,或者使用 ssh 进行文件传输,任何可以与 Linux 实体机器进行网络文件传输的工具都可以在该服务器上使用。
### **其它服务器使用方式**
这里列举几种推荐的使用方式,不同方式的使用场景各不相同,请您在了解各方式的优劣之后,结合自己的需求进行选择:
1. 使用 MobaXterm 进行连接,该方法可以在没有桌面环境的情况下,转发单个应用的图形界面。例如您可以选择一个高性能的命令行界面,安装 Pycharm 之后在远程机器上使用图形化的 Pycharm 界面。
2. 使用 vscode 的 remote-ssh 插件远程连接,该方法可以省去 ftp 服务器,直接打开远程服务器中的工程,并进行文件的上传下载和修改、程序的修改和运行。
3. 直接使用 powershell 等工具 ssh 远程连接。
## 参考资料
1. [为实验室建立公用 GPU 服务器](https://abcdabcd987.com/setup-shared-gpu-server-for-labs/)
2. [实验室 GPU 服务器的 LXD 虚拟化](https://github.com/shenuiuin/LXD_GPU_SERVER)
3. [OpenVZ](https://wiki.openvz.org/Main_Page)
4. [LXC](https://linuxcontainers.org/)
5. [LXD](https://ubuntu.com/lxd)
6. [Docker](https://docker.com)
7. [NVIDIA container toolkit install guide](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html)
8. [LXD networking issue](https://discuss.linuxcontainers.org/t/ubuntu-22-04-lxd-networking-issue-not-getting-ips-and-solution-please-verify-correctness/14739)
9. [Change cgroup enabled](https://askubuntu.com/questions/1406329/how-to-run-cgexec-without-sudo-as-current-user-on-ubuntu-22-04-with-cgroups-v2)
10. [Xen vs. KVM Comparison of Hypervisors](https://storware.eu/blog/xen-vs-kvm-comparison-of-hypervisors/)
11. [Supermicro Intelligent Management](https://www.supermicro.com/en/solutions/management-software/bmc-resources)
12. [KVM: Creating a bridged network](https://fabianlee.org/2022/09/20/kvm-creating-a-bridged-network-with-netplan-on-ubuntu-22-04/)

View File

@ -0,0 +1,138 @@
---
title: 开源LLM模型及社区项目调研
createTime: 2023/07/28 20:50:46
author: yuany3721 danc
tags:
- LLM
categories:
- blog
---
> **注意:**
>
> **该博客内容不对真实性、专业性作出任何保障,仅作记录参考使用,如有错误欢迎联系指正**
>
> **本调研内容截止日期为 2023 年 7 月 28 日,由于 LLM 的强时效性,您在进行参考时务必确认相关内容是否接近此日期及此日期之后的更新或修改**
## 引言
近年来大型语言模型Large Language ModelLLM取得了显著的进展。
其中GPT-4 作为代表性的语言模型,在文本生成、问答系统和对话生成方面表现出色。然而,由于特定场景对隐私性和准确性的要求,需要寻找一种能够在本地部署大型语言模型并能提供准确回答的解决方案。
具体到本次调研,简单列出需求如下:
1. 在 24G 显存条件下可以完成项目部署;
2. 可部署的模型对中文有一定支持;
3. 项目提供给用户的答案应当是足够可靠的;
4. 项目要便于部署、维护,有一定的社区生态支持。
## LLM 规模与 GPU 需求
通常大型语言模型Large Language ModelLLM的规模会在模型名称中使用类似于`7B`的关键词,用来表示该模型的参数规模为 70 亿。一般性地,模型参数越多,模型效果越好,对硬件的需求也越高。
在 LLM 的部署过程中,可以采用模型量化技术对模型参数进行压缩,以降低硬件需求、提升计算速度。常见的量化等级包括`FP16``BF16``INT8``INT4`,分别代表使用 16 位浮点数、16 位浮点数Google Brain Floating、8 位整数和 4 位整数进行近似计算。据不可靠来源,对模型进行量化可能会使模型更容易出现幻觉,因此本次部署中在相似条件下优先选择`FP16``BF16`精度进行部署。
以[ChatGLM2-6B](https://huggingface.co/THUDM/chatglm2-6b)为例,在不同的量化等级下所需的最小显存如下:
| **量化等级** | **编码 2048 长度的最小显存** | **生成 8192 长度的最小显存** |
| ------------ | ---------------------------- | ---------------------------- |
| FP16 / BF16 | 13.1 GB | 12.8 GB |
| INT8 | 8.2 GB | 8.1 GB |
| INT4 | 5.5 GB | 5.1 GB |
一般而言,`7B`规模的模型以`INT4`量化需要 5G 显存,在此基础上参数规模每提高$n$倍,需要的显存大小变为$2^n$。如果以 16 位浮点数精度部署模型24G 显存能运行的最大模型为 14B 左右。
### **量化对模型性能的影响**
GLM 团队也测试了[量化对模型性能的影响](https://github.com/THUDM/ChatGLM2-6B#%E6%8E%A8%E7%90%86%E6%80%A7%E8%83%BD)。结果表明,量化对模型性能的影响在可接受范围内。
| ChatGLM-6B 量化等级 | Accuracy ([MMLU](https://github.com/hendrycks/test)) | Accuracy ([C-Eval dev](https://cevalbenchmark.com/static/leaderboard.html)) |
| ------------------- | ---------------------------------------------------- | --------------------------------------------------------------------------- |
| BF16 | 45.47 | 53.57 |
| INT4 | 43.13 | 50.30 |
## 模型选取
在模型选取阶段我们参考了一些国内外各模型测评方案、LLM 跟踪榜单,主要包括以下内容:
1. **评测集**
- [MMLU](https://github.com/hendrycks/test):一个包含 57 个多选任务的英文评测数据集,涵盖了初等数学、美国历史、计算机科学、法律等,难度覆盖高中水平到专家水平,在[Hugging Face](https://huggingface.co/)上提供了[Open LLM Leaderboard](https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard)测试信息统计。
- [C-Eval](https://github.com/SJTU-LIT/ceval):一个全面的中文基础模型评估套件,涵盖了 52 个不同学科的 13948 个多项选择题,在[官网](https://cevalbenchmark.com/index_zh.html)提供了[C-Eval 排行榜](https://cevalbenchmark.com/static/leaderboard_zh.html)。
- [Gaokao](https://github.com/OpenLMLab/GAOKAO-Bench):由复旦大学研究团队构建的基于中国高考题目的综合性考试评测集,包含多科目多题型,并提供了 9 种模型的评测结果。
- [AGIEval](https://arxiv.org/pdf/2304.06364.pdf):用于评估基础模型在与人类认知和解决问题相关的任务中的一般能力,基于普通大学入学考试、数学竞赛、律师资格考试等 20 项面向普通考生的官方、公开、高标准的入学和资格考试构建。
- [CMMLU](https://github.com/haonan-li/CMMLU):一个综合性的中文评估基准,专门用于评估语言模型在中文语境下的知识和推理能力,涵盖了从基础学科到高级专业水平的 67 个主题,提供了 14 种 LLM 的评测结果。
- [PromptCBLUE](https://github.com/michael-wzhu/PromptCBLUE):将 16 种不同的医疗场景 NLP 任务转化为基于提示的语言生成任务形成的首个中文医疗场景的 LLM 评测基准,当前在[阿里巴巴天池大赛平台](https://tianchi.aliyun.com/competition/entrance/532084/introduction)上线进行开放评测。
2. **LLM 跟踪榜单**
- [An Awesome Collection for LLM in Chinese](https://github.com/HqWu-HITCS/Awesome-Chinese-LLM):已收集超过 100 个中文 LLM 相关的开源模型、应用、数据集及教程。
- [CLiB 中文大模型能力评测榜单(持续更新)](https://github.com/jeinlee1991/chinese-llm-benchmark):提供分类能力、信息抽取能力、阅读理解能力、表格问答能力等多个维度的大模型评测结果。
- [寻找那些 ChatGPT/GPT4 开源“平替”们](https://github.com/chenking2020/FindTheChatGPTer)ChatGPT/GPT4 开源“平替”汇总包括自主模型、Alpaca 模式微调模型、AGI 项目、榜单、语料等多维度内容。
## 相关开源项目对比
基于以上调研,项目的选取范围定为:支持本地知识库的 LLM 调用项目。
初步选取符合要求的项目有三个:[langchain-ChatGLM基于本地知识库的 ChatGLM 等大语言模型应用实现](https://github.com/chatchat-space/langchain-ChatGLM)、[闻达:一个大规模语言模型调用平台](https://github.com/wenda-LLM/wenda)、[gpt_academicGPT 学术优化](https://github.com/binary-husky/gpt_academic)。
模型方面,当前最优 LLM 模型为[`ChatGLM2-6B`](https://github.com/THUDM/ChatGLM2-6B),知识库向量化模型选择[`m3e-base`](https://huggingface.co/moka-ai/m3e-base)。
### **langchain-ChatGLM**
langchain-ChatGLM 是一个利用[langchain](https://github.com/hwchase17/langchain)思想实现的基于本地知识库的问答应用,目标期望建立一套对中文场景与开源模型支持友好、可离线运行的知识库问答解决方案。
![langchain-ChatGLM](./img/langchain_chatglm.png)
该项目主要特点包括:
- 支持 Docker 部署,同时提供开发部署方案
- 支持 ChatGLM、ChatYuan 等多种模型,支持通过 fastchat API 调用任意 LLM
- 知识库接入非结构化文档,当前已支持 md、pdf、docx、txt 格式,支持 jpg 与 png 格式图片的 OCR 文字识别
- 路线图未来计划实现的功能中包含结构化数据csv、Excel、SQL 等)接入、知识图谱/图数据库接入、Agent 实现
- 支持多种知识库 Embedding 模型
- 支持搜索引擎问答
### **闻达**
闻达项目的设计目标是实现针对特定环境的高效内容生成,同时考虑个人和中小企业的计算资源局限性,以及知识安全和私密性问题。该项目的主要特点包括:
- 支持 chatGLM-6B\chatGLM2-6B、chatRWKV、llama 系列、openai api 等多种模型接入
- 支持本地离线向量库rtst、本地搜索引擎fess、在线搜索引擎三种知识库构建模式
- 特色 Auto 脚本:通过开发插件形式的 JavaScript 脚本,为平台附件功能,实现包括但不限于自定义对话流程、访问外部 API、在线切换 LoRA 模型
- 使用宏调用 API 的方式接入 Word 文档
值得一提的是,由社区成员 AlanLee1996 贡献的[Wenda-Webui](https://github.com/AlanLee1996/wenda-webui)提供了类似 ChatPDF 的文档对话功能。
### **gpt_academic**
gpt_academic 是为 ChatGPT/GLM 设计的图形交互界面,特别优化论文阅读/润色/写作体验,模块化设计,主要特点包括:
- 支持复旦 MOSS、llama、rwkv、newbing、claude、claude2 等多种模型接入
- 支持多种模型混合调用,支持模型异步加载
- 支持 latex 格式论文翻译、总结、润色,支持 latex 公式渲染
- 支持自定义强大的函数插件,插件支持热更新
- 丰富的插件库,支持 PDF latex 论文解析、代码工程解释、批量注释生成等多种功能

View File

@ -0,0 +1,121 @@
---
title: ZeroTier组网的简单应用
createTime: 2024/07/01 23:06:45
tags:
- ZeroTier
categories:
- blog
---
## 需求
1. 在不同地点的网络设备虚拟组网
2. 虚拟网络中各设备可以访问`172.16.60.0/23`内网网段设备
## 创建 ZeroTier 虚拟网络
参考[官方文档](https://docs.zerotier.com/)
## 配置 moon 节点
直接通过 ZeroTier 官方节点建立网络连接延迟太高,使用本地服务器建立 moon 节点进行加速。
1. 基础配置
```bash
# 安装zerotier-one
curl -s https://install.zerotier.com | sudo bash
# 加入创建好的虚拟网络
sudo zerotier-cli join xxxxxxxx
```
在 ZeroTier Central 网络管理的 Members 中选择该设备进行授权,并勾选`Allow Ethernet Bridging`
2. 生成并应用 moon 配置
参考[Private Root Servers](https://docs.zerotier.com/roots)
```bash
# 生成moon配置文件
cd /var/lib/zerotier-one
sudo zerotier-idtool initmoon identity.public >> moon.json
# 编辑配置文件
# 将"stableEndpoints": [] 修改成 "stableEndpoints": ["ServerIP/9993"]ServerIP是服务器的公网IP
# 生成moon文件
sudo zerotier-idtool genmoon moon.json
# 查看生成的moon文件
ls /var/lib/zerotier-one
# 应用moon文件
sudo mkdir moons.d
sudo mv 000000xxxxxxxxxx.moon moons.d
sudo service zerotier-one restart
```
3. 使用 moon 节点
```bash
sudo zerotier-cli orbit xxxxxxxxxx xxxxxxxxxx
# 这里xxxxxxxxxx是前面生成的moon文件除了那些0之外的部分即节点ID
```
4. 如何检查是否成功应用 moon 节点
```bash
sudo zerotier-cli listpeers
```
该命令会输出一行有关 moon 的信息,如果没有成功应用,应该类似于`200 listpeers xxxxxxxxx - -1 - MOON`,通常情况下是防火墙的问题,需要打开`9993/udp`,包括服务器防火墙、运营商安全组之类的。
也可以通过虚拟网络中设备相互 ping 看延迟检查,如果成功应用 moon 节点,相互 ping 的延迟最坏情况下是比各自 ping moon 节点延迟之和略高几 ms。以我的网络为例A 设备与 moon 节点 ping 约 30msB 设备与 moon 节点 ping 约 20ms无 moon 节点时 AB 互 ping 约 300+msmoon 节点生效时互 ping 约 30+ms。
## 与物理网络组网
参考[Route between ZeroTier and Physical Networks](https://docs.zerotier.com/route-between-phys-and-virt#configure-iptables)
1. 网络说明
希望加入了 ZeroTier 虚拟网络的设备可以访问`172.16.60.0/23`内网网段设备,该网段的默认网关及其它设备的配置无法修改,我有一台可以作为跳板机的内网服务器。
2. 配置 ZeroTier 虚拟网络
配置 ZeroTier 自动分配 ipv4 地址池为`172.16.58.0``172.16.59.254`。在 ZeroTier Central 的网络管理中,添加 routedestination 为`172.16.58.0/23`,空置 via提交后显示`172.16.58.0/23 (LAN)`
3. 配置内网服务器
在内网服务器上安装 zerotier-one 并加入虚拟网络,在 ZeroTier Central 网络管理的 Members 中选择该网络进行授权,并勾选`Allow Ethernet Bridging`
假定该服务器的地址为`172.16.58.58`,它在内网中的地址为`172.16.61.61`。此时应该可以从 moon 节点使用`172.16.58.58`正常访问到该内网服务器。
在 ZeroTier Central 的网络管理中,添加 routedestination 为`172.16.60.0/22`via 为`172.16.58.58`,提交后显示`172.16.58.0/23 via 172.16.58.58`
**注意!!!这里的掩码必须要大于该网络本来的掩码!!!** 官方解释如下:
> Configure the destination route as slightly larger than the actual physical subnet, here /23 instead of /24 (a smaller number is a bigger subnet in this notation) This makes devices that are on both the physical and the ZeroTier network prefer the physical connection.
回到内网服务器配置 NAT
```bash
# 查看网络接口
ip a
# 找到172.16.58.58对应的ztxxxx以及172.16.61.61对应的enpxxxx
PHY_IFACE=enpxxxx
ZT_IFACE=ztxxxx
# 配置NAT
sudo iptables -t nat -A POSTROUTING -o $PHY_IFACE -j MASQUERADE
sudo iptables -A FORWARD -i $PHY_IFACE -o $ZT_IFACE -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i $ZT_IFACE -o $PHY_IFACE -j ACCEPT
```
持久化路由表,使重启有效:
```bash
# 持久化
sudo apt install iptables-persistent
# 备份iptables
sudo cp /etc/iptables/rules.v4 /etc/iptables/rules.v4.bak
# 更新路由表
sudo sh -c "iptables-save > /etc/iptables/rules.v4"
```
至此,所有加入 ZeroTier 的设备均可以直接访问`172.16.60.0/23`网段的内网设备了。但是如果内网设备想访问`172.16.58.0/23`网段设备,仍然需要加入 ZeroTier 虚拟网络。

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1,131 @@
---
title: AD9910及控制板使用说明
createTime: 2026/04/02 20:26:36
---
## 概述
AOM的驱动信号及扫频控制信号由AD9910及其控制板提供本文档旨在对硬件连接、软件使用作出基本说明。
![AD9910](./img/AD9910.png)
后面称为“核心板”
![STMCTR](./img/STMCTR.png)
后面称为“控制板”
## 硬件说明
### 核心板
![AD9910](./img/AD9910_E.png)
1. 外部连接
- 通过左侧`DC-5V`连接到台式电源提供5V供电
- 通过W1跳线帽紫色方框进行时钟源选择跳线帽短接左侧两个引脚时为晶振提供时钟推荐短接右侧两个引脚时为外部时钟源蓝色方框
- DDS输出为靠近核心板中间的SMA接头红色方框
- 通过下方排针与控制板连接(绿色方框)
2. 注意事项
- 重要DDS输出含有约1.5V的直流成分, **!!!必须!!!** 连接隔直器后再接入后级设备
- (重要)外部时钟源输入时,输入频率 **!!!必须 ** 为40MHz推荐信号幅值为0~3V推荐信号类型为方波
- (重要)**注意与控制板的排线连接方向!!!没有防呆设计!!!连接错误可能直接烧掉芯片**,默认已经连接好
- (推荐)上电前将模块开关(红色圆框)置于关闭状态
- (不推荐)核心板出现输出异常时,直接通过开关断电重启核心板,这种硬件重置的方式只有在软件重置无效时才使用
### 控制板
![STMCTR](./img/STMCTR_E.png)
1. 外部连接
- 通过右侧USB接口连接到上位机上位机同时可以为模块提供5V供电使用串口与上位机通信
- 通过左侧SMA接头红色方框与1pps时钟源连接
- 通过W1跳线帽紫色方框进行时钟源选择跳线帽短接左侧两个引脚时为晶振提供时钟推荐短接右侧两个引脚时为外部时钟源蓝色方框
- 通过右上排针与核心板连接(绿色方框)
2. 注意事项
- 重要外部1pps时钟输入幅值**必须**大于1.8V$V_{peak-to-peak}$)为了避免意外噪声导致意外触发建议输入幅值大于2V蓝色方框处的蓝色LED灯在每次触发信号到来时会切换开关状态作为时钟信号是否正常给到控制板的依据
- (重要)注意与控制板的排线连接方向,**有防呆设计,不要硬插**,默认已经连接好
- 推荐直接使用USB接口为模块供电如果使用USB-HUB需要注意HUB连接设备过多时将USB-HUB连接上额外供电`DC-5V`供电接口只在供电无法满足时才需要连接
- (推荐)上电前将模块开关(右侧红色圆框)置于关闭状态
- (推荐)核心板出现输出异常时,可以通过开关(左右侧红色圆框均可)断电重启控制板,达到软件重置核心板的效果
- (不重要)核心板的`DC-5V`不要与控制板的`DC-5V`使用同一电源供电以减小对DDS输出噪声的影响
### 启动顺序
1. 按照外部连接说明连接核心板和控制板,检查模块开关均处于关闭状态(板卡上无红灯亮起)
2. 打开台式电源供电开关
3. 打开DDS模块开关板上红灯亮起
4. 打开控制板模块开关(板上红灯亮起)
## 软件配置
### 相关文件
服务端:[server_web.py](/files/AD9910/server_web.py)
服务端依赖:[requirements.txt](/files/AD9910/requirements.txt)
客户端调用示例:[client_web.py](/files/AD9910/client_web.py)
### 使用说明
1. 下载依赖`requirements.txt`并使用pip安装依赖
2. (重要)程序运行前必须先确认已经正确连接控制板
3. 运行服务端程序`server_web.py`,程序运行后会自动选择第一个设备描述中含有`STM`的串口进行连接通信
4. 编写并运行客户端程序
### 软件接口
`server_web.py`成功运行后,控制台会输出如下内容,表明服务端已经成功连接上控制板端口,并在`http://127.0.0.1:56789`监听客户端请求:
```bash
INFO: Started server process [xxxxx]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:56789 (Press CTRL+C to quit)
```
`client_web.py`中包含了所有接口的调用样例代码,以下是服务端的接口说明:
| 功能 | 请求路径 | 请求类型 | 请求体内容 | 成功调用返回值 | 备注 |
| -------------- | -------- | -------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| 测试指令 | `/test/` | GET | 无 | `{"res": 1}` | |
| 清空1pps序列 | `/ctr/` | POST | `{"text": "SYS:TIME:CLR"}` | `{"res": "SYS:TIME:CLR"}` | |
| 清空1pps序列 | `/ctr/` | POST | `{"text": "SYS:TIME:GET?"}` | 序列长度不足10时<br/>`{"error": "now queue size n"}`<br/>序列长度足够时:<br/>`["2024-01-23 01:23:45.123456", ...]` | 序列长度不同时,返回类型不同 |
| 扫频一级触发 | `/ctr/` | POST | `{"text": "SYS:CURVE:START"}` | `{"res": "SYS:CURVE:START"}` | |
| 结束扫频 | `/ctr/` | POST | `{"text": "SYS:CURVE:STOP"}` | `{"res": "SYS:CURVE:STOP"}` | 不会立即停止会在扫完当前6MHz范围后不再进行下一段扫频 |
| 软件重置AD9910 | `/ctr/` | POST | `{"text": "SYS:RESET"}` | `{"res": "SYS:RESET"}` | |
**备注:**
1. 请求路径为`/test/`表示该请求的实际请求地址为`http://127.0.0.1:56789/test/`
2. 请求类型为`POST`的请求体需要用`json.dumps`编码
3. 所有调用因为网络原因不成功的,均可以用`response.status_code != 200`判断
4. (强烈建议)使用`client_web.py`封装好的接口进行接口调用
5. (建议)使用虚拟环境运行代码,参考[python虚拟环境配置](/blogs/note/python/2024-07-31.md)

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

View File

@ -0,0 +1,42 @@
---
title: GLM3 API 使用指北
createTime: 2026/04/02 20:26:36
---
## FastAPI docs
由FastAPI自动生成的API[说明页面](http://yuany3721.site:6017/docs),由[API部署代码](https://github.com/THUDM/ChatGLM3/blob/main/openai_api_demo/api_server.py)中注释自动生成,基于[OpenAI API](https://platform.openai.com/docs/api-reference/chat)。
API入口
- "/health": 响应API运行状态返回200则运行正常
- "/v1/chat/completions": 响应文本对话请求,可选是否流式输出
- "/v1/embeddings": 响应一组列表式文本对话请求
更多代码说明:
> This script implements an API for the ChatGLM3-6B model,
> formatted similarly to OpenAI's API (https://platform.openai.com/docs/api-reference/chat).
> It's designed to be run as a web server using FastAPI and uvicorn,
> making the ChatGLM3-6B model accessible through OpenAI Client.
>
> Key Components and Features:
>
> - Model and Tokenizer Setup: Configures the model and tokenizer paths and loads them.
> - FastAPI Configuration: Sets up a FastAPI application with CORS middleware for handling cross-origin requests.
> - API Endpoints:
> - "/v1/models": Lists the available models, specifically ChatGLM3-6B.
> - "/v1/chat/completions": Processes chat completion requests with options for streaming and regular responses.
> - "/v1/embeddings": Processes Embedding request of a list of text inputs.
> - Token Limit Caution: In the OpenAI API, 'max_tokens' is equivalent to HuggingFace's 'max_new_tokens', not 'max_length'.
> For instance, setting 'max_tokens' to 8192 for a 6b model would result in an error due to the model's inability to output
> that many tokens after accounting for the history and prompt tokens.
> - Stream Handling and Custom Functions: Manages streaming responses and custom function calls within chat responses.
> - Pydantic Models: Defines structured models for requests and responses, enhancing API documentation and type safety.
> - Main Execution: Initializes the model and tokenizer, and starts the FastAPI app on the designated host and port.
## API调用示例
参考[api-demo](https://github.com/THUDM/ChatGLM3/blob/main/openai_api_demo/openai_api_request.py)
修改第15行`base_url`为目标URL。

View File

@ -0,0 +1,11 @@
---
pageLayout: friends
title: 友情链接
description:
permalink: /friends/
list:
- name: 老王HUB
link: https://increcrazer.github.io/
avatar: https://increcrazer.github.io/medias/wya.png
desc: 光芯片、QKD大拿Caeser Wang
---

View File

@ -0,0 +1,19 @@
---
title: DNS解析类型
createTime: 2021/08/30
tags:
- DNS
categories:
- 随记
---
1. AAddress记录 将域名指向 IP 地址Ipv4
2. MXMail Exchange记录 邮件交换记录,用于电子邮件系统发邮件时根据收信人的地址后缀来定位邮件服务器
3. CNAMECanonical Name记录 通常称别名解析,可实现将域名指向另一个域名或 IP 地址
4. URLUniform Resource Locator转发 网址转发,如果没有一个独立的 IP 地址或者有一个域名 B想在访问 A 域名时访问到 B 域名的内容,这时就可以通过 URL 转发来实现。URL 转发可以转发到某一个目录或某一个文件上,而 CName 不可以
5. NSName Server记录 域名服务器记录,用来指定该域名由哪个 DNS 服务器来进行解析
6. AAAA 记录 将域名指向 Ipv6 地址
7. TXT 记录 文本记录
8. PTR 值Pointer 用于将一个 IP 地址映射到对应的域名,也可以看成是 A 记录的反向解析
9. SRV 记录 服务定位器,记录了哪台服务器提供了何种服务
10. CAACertificate Authority Authorization记录 认证机构授权,限定了特定域名颁发的证书和 CA证书颁发机构之间的联系

View File

@ -0,0 +1,532 @@
---
title: 常见gcc编译问题解决方法集
author: 一见
createTime: 2021/09/28
tags:
- gcc
- 转载
categories:
- 随记
---
> 作者:一见
> 参考[https://www.cnblogs.com/aquester/p/9891584.html](https://www.cnblogs.com/aquester/p/9891584.html)
除非明确说明,本文内容仅针对 x86/x86_64 的 Linux 开发环境,有朋友说 baidu 不到,开个贴记录一下(加粗字体是关键词):
`-Wl,-Bstatic`指定链接静态库,使用`-Wl,-Bdynamic`指定链接共享库,使用示例:
`-Wl,-Bstatic -lmysqlclient_r -lssl -lcrypto -Wl,-Bdynamic -lrt -Wl,-Bdynamic -pthread -Wl,-Bstatic -lgtest`
"-Wl"表示是传递给链接器 ld 的参数,而不是编译器 gcc/g++的参数。)
1. 下面是因为没有指定链接参数`-lz``/usr/lib/libz.so``/usr/lib/libz.a`
```text
/usr/local/mysql/lib/mysql/libmysqlclient.a(my_compress.c.o): In function `my_uncompress':
/home/software/mysql-5.5.24/mysys/my_compress.c:122: undefined reference to `uncompress'
/usr/local/mysql/lib/mysql/libmysqlclient.a(my_compress.c.o): In function `my_compress_alloc':
/home/software/mysql-5.5.24/mysys/my_compress.c:71: undefined reference to `compress'
```
2. 下面是因为没有指定编译链接参数`-pthread`(注意不仅仅是`-lpthraed`
```text
/usr/local/mysql/lib/mysql/libmysqlclient.a(charset.c.o): In function `get_charset_name':
/home/zhangsan/mysql-5.5.24/mysys/charset.c:533: undefined reference to `pthread_once'
```
3. 下面这个是因为没有指定链接参数`-lrt`
```text
/usr/local/thirdparty/curl/lib/libcurl.a(libcurl_la-timeval.o): In function `curlx_tvnow':
timeval.c:(.text+0xe9): undefined reference to `clock_gettime'
```
4. 下面这个是因为没有指定链接参数`-ldl`
```text
/usr/local/thirdparty/openssl/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_globallookup':
dso_dlfcn.c:(.text+0x4c): undefined reference to `dlopen'
dso_dlfcn.c:(.text+0x62): undefined reference to `dlsym'
dso_dlfcn.c:(.text+0x6c): undefined reference to `dlclose'
```
5. 下面这个是因为指定了链接参数`-static`,它的存在,要求链接的必须是静态库,而不能是共享库
```text
ld: attempted static link of dynamic object
```
如果是以`-L``-l`方式指定,则目录下必须有`.a`文件存在,否则会报`-l`的库文件找不到:`ld: cannot find -lACE`
6. GCC 编译遇到如下的错误,可能是因为在编译时没有指定`-fPIC`,记住:`-fPIC`即是编译参数,也是链接参数
```text
relocation R_x86_64_32S against `vtable for CMyClass` can not be used when making a shared object
```
7. 下面的错误表示 gcc 编译时需要定义宏`__STDC_FORMAT_MACROS`,并且必须包含头文件`inttypes.h`
```text
test.cpp:35: error: expected `)' before 'PRIu64'
```
8. 下面是因为在 x86 机器32 位)上编译没有指定编译参数`-march=pentium4`
```text
../../src/common/libmooon.a(logger.o): In function `atomic_dec_and_test':
../../include/mooon/sys/atomic_gcc.h:103: undefined reference to `__sync_sub_and_fetch_4'
```
9. 下列错误可能是因为多了个`}`
```text
error: expected declaration before '}' token
```
10. 下列错误可能是因为少了个`}`
```text
error: expected `}' at end of input
```
11. 下面这个错误是编译一个共享库时,该共享库依赖的一静态库编译时没有加`-fPIC`参数,解决方法为带`-fPIC`重新编译被依赖的静态库
```text
relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
```
12. 下面这个错误,是因为头文件中使用`_syscall0(pid_t, gettid)`不当引起的
```text
./test.o: In function `gettid()':
./test.h:17: multiple definition of `gettid()'
```
正确的用法是使用"inline"或"static inline"修饰一下:
```text
inline _syscall0(pid_t, gettid)
```
```text
static inline _syscall0(pid_t, gettid)
```
当然也可以这样:
在.h 头文件中:`extern "C" pid_t gettid(void);`
在.cpp 文件中:`_syscall0(pid_t, gettid)`
\_syscall0 是一个宏,定义一个函数的实现。
13. 下列编译告警是因为一个 static 类型的函数未被使用
```text
my.cpp:364: warning: 'int my_function(const cgicc::Cgicc&, const std::string&)' defined but not used
```
只需使用`__attribute__((unused))`修饰函数的声明即可:
```text
static int __attribute__((unused)) my_function(const cgicc::Cgicc&, const std::string&);
```
14. 执行 thrift 的 configure 时遇到如下的错误thrift-0.9.0 和 thrift-0.9.1 遇到过):
```text
checking for setsockopt in -lsocket... no
checking for BN_init in -lcrypto... no
configure: error: "Error: libcrypto required."
```
原因可能是因为编译安装 openssl 时指定了`--prefix`,比如`--prefix=/usr/local/thirdparty/openssl`,可这样解决:
不指定`thrift``configure``--with-openssl=/usr/local/thirdparty/openssl`,改为:
```text
CPPFLAGS="-I/usr/local/thirdparty/openssl/include" LDFLAGS="-ldl -L/usr/local/thirdparty/openssl/lib"
```
替代它就 OK 了。
15. 下面这个编译错误(表现为 g++进入死循环),可能是由于缺少右大括号`}`导致的,比如定义名字空间时少了`}`
```text
/usr/include/c++/4.1.2/tr1/type_traits:408: error: 'size_t' is not a member of 'db_proxy::std'
/usr/include/c++/4.1.2/tr1/type_traits:408: error: 'size_t' is not a member of 'db_proxy::std'
/usr/include/c++/4.1.2/tr1/mu_iterate.h:49: error: 'std::tr1' has not been declared
/usr/include/c++/4.1.2/tr1/mu_iterate.h:49: error: 'std::tr1' has not been declared
/usr/include/c++/4.1.2/tr1/bind_iterate.h:78: error: 'std::tr1' has not been declared
/usr/include/c++/4.1.2/tr1/bind_iterate.h:78: error: 'std::tr1' has not been declared
/usr/include/c++/4.1.2/tr1/bind_iterate.h:78: error: 'std::tr1' has not been declared
```
16. protoc 编译错误,下面错误是因为没有在.proto 文件所在目录下执行:
```text
/tmp/test.proto: File does not reside within any path specified using --proto_path (or -I). You must specify a --proto_path which encompasses this file. Note that the proto_path must be an exact prefix of the .proto file names -- protoc is too dumb to figure out when two paths (e.g. absolute and relative) are equivalent (it's harder than you think).
```
解决办法有两个:一是在.proto 文件所在目录下执行 protoc二是为 protoc 指定参数--proto_path参数值为.proto 文件所在目录。
17. 下面这个编译错误,可能是因为在全局域内调用一个类对象的成员函数,全局域内是不能直接执行函的:
```text
error: expected constructor, destructor, or type conversion before '->' token
```
18. 下面这个错误是因为没有链接 OpenSSL 的 libcrypto 库,或者使用了静态库,而顺序不对:
```text
undefined symbol: EVP_enc_null
```
19. 下列是链接错误,不是编译错误,加上`-pthread`即可,注意不是`-lpthread`
```text
/usr/local/mysql/lib/mysql/libmysqlclient.a(charset.c.o): In function `get_charset_name':
/home/software/mysql-5.5.24/mysys/charset.c:533: undefined reference to `pthread_once'
/usr/local/mysql/lib/mysql/libmysqlclient.a(charset.c.o): In function `get_charset_number':
```
20. 依赖 OpenSSL假设安装在/usr/local/thirdparty/openssl-1.0.2a)时,如果
```text
./configure --prefix=/usr/local/thirdparty/libssh2-1.6.0 --with-libssl-prefix=/usr/local/thirdparty/openssl-1.0.2a
```
时遇到如下错误:
```text
configure: error: No crypto library found!
Try --with-libssl-prefix=PATH
or --with-libgcrypt-prefix=PATH
or --with-wincng on Windows
```
可以如下方法解决:
```text
./configure --prefix=/usr/local/thirdparty/libssh2-1.6.0 --with-openssl CPPFLAGS="-I/usr/local/thirdparty/openssl-1.0.2a/include" LDFLAGS="-L/usr/local/thirdparty/openssl-1.0.2a/lib"
```
21. 错误`error: expected primary-expression before ; token`可能是因为如下原因:
```text
UserInfoInternal* user_info_internal = new UserInfoInternal;
delete user_info; // 这里应当是user_info_internal
```
22. 下面这个编译错误的原因是定义字符串宏时没有加双引引号:
```text
example.cpp:563:16: error: too many decimal points in number
```
如定义成了:`#define IP1 127.0.0.1`,改成`#define IP1 "127.0.0.1"`后问题即解决。
23. 下面这个编译错误是因为 g++命令参数没写对,多了个`-`
```text
g++: -E or -x required when input is from standard input
```
如:
```text
CPPFLAGS=-pthread -
g++ -g -o $@ $^ $(CPPFLAGS) $(LDFLAGS)
```
24. `libjson_7.6.1`编译错误:
```text
makefile:180: Extraneous text after `else' directive
makefile:183: *** only one `else' per conditional. Stop.
```
解决办法:
找到 makefile 文件的第 180 行,将`else ifeq ($(BUILD_TYPE), debug)`,改成两行内嵌方式:
```text
# BUILD_TYPE specific settings
ifeq ($(BUILD_TYPE), small)
CXXFLAGS = $(cxxflags_small)
else
ifeq ($(BUILD_TYPE), debug) # 不能和else同一行否则Makefile语法错误不支持else ifeq
CXXFLAGS = $(cxxflags_debug)
libname := $(libname_debug)
else
CXXFLAGS ?= $(cxxflags_default)
endif
endif
```
可以通过设置环境变量来设置`BUILD_TYPE`,如:`export BUILD_TYPE=debug`
也可以通过环境变量来设置`make install`时的安装目录,如:`export prefix=/usr/local/libjson`
相关小知识:
在 Makefile 文件中,`prefix=/usr``prefix?=/usr`,是有区别的,前者赋值不能通过环境变量覆盖,后者则可以使用环境变量的值覆盖。
另外,请将第 271 行删除:
```text
cp -rv $(srcdir)/Dependencies/ $(include_path)/$(libname_hdr)/$(srcdir)
```
改成:
```text
cp -rv _internal/Dependencies/ $(include_path)/$(libname_hdr)/$(srcdir)
```
还有第 258 行前插入如一条命令:
```text
mkdir -p $(inst_path)
```
否则`cp -f ./$(lib_target) $(inst_path)`lib 将成库文件名。
25. 编译 gcc 时,如果遇到下面这个错误,这是因为运行时找不到 mpc、mpfr 和 gmp 的 so 文件:
```text
checking for x86_64-unknown-linux-gnu-nm... /data/gcc-4.8.2_src/host-x86_64-unknown-linux-gnu/gcc/nm
checking for x86_64-unknown-linux-gnu-ranlib... ranlib
checking for x86_64-unknown-linux-gnu-strip... strip
checking whether ln -s works... yes
checking for x86_64-unknown-linux-gnu-gcc... /data/gcc-4.8.2_src/host-x86_64-unknown-linux-gnu/gcc/xgcc -B/data/gcc-4.8.2_src/host-x86_64-unknown-linux-gnu/gcc/ -B/data/gcc-4.8.2/x86_64-unknown-linux-gnu/bin/ -B/data/gcc-4.8.2/x86_64-unknown-linux-gnu/lib/ -isystem /data/gcc-4.8.2/x86_64-unknown-linux-gnu/include -isystem /data/gcc-4.8.2/x86_64-unknown-linux-gnu/sys-include
checking for suffix of object files... configure: error: in `/data/gcc-4.8.2_src/x86_64-unknown-linux-gnu/libgcc':
configure: error: cannot compute suffix of object files: cannot compile
See `config.log' for more details.
make[2]: *** [configure-stage1-target-libgcc] 错误 1
```
所以只需要如下操作下即可:
```text
export LD_LIBRARY_PATH=/usr/local/mpc/lib:/usr/local/mpfr/lib:/usr/local/gmp/lib:$LD_LIBRARY_PATH
```
gcc-4.8.2 依赖 mpc、mpfr 和 gmp
```text
./configure --prefix=/usr/local/gcc-4.8.2 --with-mpc=/usr/local/mpc-1.0.3 --with-mpfr=/usr/local/mpfr-3.1.3 --with-gmp=/usr/local/gmp-6.0.0
```
而 mpc 又依赖于mpfr 和 gmp
```text
./configure --prefix=/usr/local/mpc-1.0.3 --with-mpfr=/usr/local/mpfr-3.1.3 --with-gmp=/usr/local/gmp-6.0.0
```
26. 编译 gcc 时,如果遇到下面这个错误:
```text
fatal error: gnu/stubs-32.h: No such file or directory
```
这是因为在 x86_64 上,默认会编译出 32 位和 64 位两个版本。这样编译 32 位时,需要机器上有 32 位的 libc 头文件和库文件,但一些机器上可能没有,比如没有/lib 目录,只有/lib64 目录,这表示不支持 32 位的 libc。为解决这个问题可以禁止编译 32 位版本,在 configure 时带上参数`--disable-multilib`,或者安装 32 位版本的 glibc。
27. 某次编译遇到如下这样一个链接错误:
```text
redis_dbi.cpp:224: undefined reference to `sdscatlen(char*, void const*, unsigned long)'
```
按常理,这个错误要么是没有指定相应的库,要么是静态库间的顺序问题。
但经过检查,这两个原因,而是因为 gcc 和 g++混用原因:
1. 库 libhiredis.a 和 libhiredis.so 是由 gcc 编译出来的
2. 而调用它的代码是由 g++编译的,因此导致了此问题。
问题的解决办法有两个:
1. 修改 sdscatlen 所在的.h 文件,将代码使用
```c
#ifdef __cplusplus
extern "C" {
#endif
```
修饰起来,或者直接使用`extern C`修饰函数 sdscatlen。
2. 不修改 redis 的代码,在引用 sds.h 时加上`extern "C" {`
```c
extern "C" {
#include "sds.h"
}`
```
上面两个办法均可,当然也可以考虑改用 g++编译 redis不过可能会遇到很多错误。
redis 对外供外部直接使用的头文件 hiredis.h 已使用了`extern "C" {`,所以不存在问题,只有当跳过 hiredis.h去使用一些内部头文件时需要注意一下。
3.
```text
x.hpp:27: error: expected identifier before string constant
x.hpp:27: error: expected `}' before string constant
x.hpp:27: error: expected unqualified-id before string constant
```
这个错误,可能是存在和枚举等同名的字符串宏,比如存在下面的宏定义:
```text
enum DBTYPE
{
UNDEFINE = 0,
MYSQL_DB = 1,
ORACLE_DB = 2
};
```
而另一.h 文件中定义了宏:
`#define MYSQL_DB "mysql"`
29. 下面这个错误是因为类成员函数的声明和定义的返回值不相同
```text
test.cpp:201:6: 错误bool foo(const string&, const string&, const string&, const string&, const string&, const HBaseRowValue&)的原型不匹配类CTest中的任何一个
bool CHBaseOper::foo(const std::string& tablename, const std::string& rowkey, const std::string& familyname, const std::string& columnname, const std::string& columnvalue, const HBaseRowValue& row_values)
^
In file included from test.cpp:8:0:
test.h:58:6: 错误备选为int foo(const string&, const string&, const string&, const string&, const string&, const HBaseRowValue&)
int foo(const std::string& tablename, const std::string& rowkey, const std::string& familyname, const std::string& columnname, const std::string& columnvalue, const HBaseRowValue& row_values);
```
30. `messenger.cpp:5: error: expected unqualified-id before ':' token`
该编译错误原因是:
```text
CMessager:CMessager()
{
}
```
即少了个冒号:
```text
CMessager::CMessager()
{
}
```
31. `unable to find a register to spill in class SIREG`
编译时如果遇到这个错误,表示遇到一个 gcc 的 bug最简单的办法是去掉编译参数中的-O3 等优化项,然后再试可能就成功了,也可以考虑指定`-fno-schedule-insns`
32. 像下面这样一大堆乱七八糟的错误,可以考虑是否为少了`}`等引起的
```text
/usr/include/c++/4.8.2/bits/stl_list.h:131:15: 错误bidirectional_iterator_tag不是命名空间tom::std中的一个类型名
typedef std::bidirectional_iterator_tag iterator_category;
^
/usr/include/c++/4.8.2/bits/stl_list.h: 在成员函数_Tp* tom::std::_List_iterator<_tp>::operator->() const中:
/usr/include/c++/4.8.2/bits/stl_list.h:150:16: 错误__addressof不是tom::std的成员
{ return std::__addressof(static_cast<_Node*>(_M_node)->_M_data); }
```
比如:
```text
namespace A { namespace B {
。。。。。。
// 下面少了一个`}`
} // namespace A { namespace B {
```
33. `crc32 cannot be used as a function`
```text
uint32_t crc32 = crc32(0L, (const unsigned char*)crc32_str.data(), crc32_str.size());
```
错误是因为函数名和变量名相同了,可以改成如下解决:
```text
uint32_t crc32 = ::crc32(0L, (const unsigned char*)crc32_str.data(), crc32_str.size());
```
34.
```text
/data/X/mooon/tools/hbase_stress.cpp: In function 'void test_write(const std::map<std::basic_string<char>, std::basic_string<char> >&)':
/data/X/mooon/tools/hbase_stress.cpp:78:117: error: invalid conversion from 'void (*)(uint8_t, const string&, uint16_t) {aka void (*)(unsigned char, const std::basic_string<char>&, short unsigned int)}' to 'mooon::sys::FunctionWith3Parameter<unsigned char, std::basic_string<char>, short unsigned int>::FunctionPtr {aka void (*)(unsigned char, std::basic_string<char>, short unsigned int)}' [-fpermissive]
stress_threads[i] = new mooon::sys::CThreadEngine(mooon::sys::bind(write_thread, i, hbase_ip, hbase_port)); ^
In file included from /data/X/mooon/tools/hbase_stress.cpp:24:0:
/data/X/mooon/tools/../include/mooon/sys/thread_engine.h:777:16: error: initializing argument 1 of 'mooon::sys::Functor mooon::sys::bind(typename mooon::sys::FunctionWith3Parameter<Parameter1Type, Parameter2Type, Parameter3Type>::FunctionPtr, Parameter1Type, Parameter2Type, Parameter3Type) [with Parameter1Type = unsigned char; Parameter2Type = std::basic_string<char>; Parameter3Type = short unsigned int; typename mooon::sys::FunctionWith3Parameter<Parameter1Type, Parameter2Type, Parameter3Type>::FunctionPtr = void (*)(unsigned char, std::basic_string<char>, short unsigned int)]' [-fpermissive]
inline Functor bind(typename FunctionWith3Parameter<Parameter1Type, Parameter2Type, Parameter3Type>::FunctionPtr function_ptr, Parameter1Type parameter1, Parameter2Type parameter2, Parameter3Type parameter3)
```
上面这个错误的意思是第一个参数的类型为
```text
void (*)(unsigned char, std::basic_string<char>, short unsigned int)
```
但传入的类型为
```text
void (*)(unsigned char, const std::basic_string<char>&, short unsigned int)
```
从上面的对比可以看出,要求函数的第二个参数为 std::string 类型,而不是 const std::string&类型。
35.
```text
conflicting declaration
has a previous declaration as
```
这个错误可能是因为头文件没有`#ifndef`,导致引入多次。
36.
```text
warning: cannot pass objects of non-POD type const struct std::basic_string<char, std::char_traits<char>, std::allocator<char> > through ...; call will abort at runtime
warning: format %s expects type char*, but argument 3 has type int
```
这个错误是因为格式化`%s`参数的值为`std::string`值,这个在运行时可能会触发`SIGILLIllegal instruction`,例如:
```text
std::string type;
std::string name;
。。。 。。。
const std::string& key = mooon::utils::CStringUtils::format_string("%s_%s", type.c_str(), name);
```
37. `'__curl_rule_01__' is negative`
这个编译错误,是因为在 64 位平台上编译 64 位程序,但 curl 库是 32 位方式编译的。
38.
```text
countable_log_writer.cpp:54:50: 错误从类型const CCounter*到类型CCounter*’的转换无效 [-fpermissive]
return (NULL == counter)? &_default_counter: counter;
^
```
错误实际出在`_default_counter`的使用上,返回的是非`const`类型的`CCounter*`
而由于函数`get_counter``const`类型函数,意味着`this`也是`const`类型,
`&_default_counter`也就成了`const CCounter*`类型。
简单的修改方法是将`_default_counter`定义成`CCounter*`指针类型,而非`CCounter`对象类型。
````text
CCounter* CCountableLogWriter::get_counter(const std::string& type) const
{
CCounter* counter = NULL;
CCounterTable::const_iterator iter = _counter_table.find(type);
if (iter != _counter_table.end())
counter = iter->second;
return (NULL == counter)? &_default_counter: counter;
}
```text
````

View File

@ -0,0 +1,13 @@
---
title: 利用私钥生成公钥
createTime: 2022/04/18
tags:
categories:
- 随记
---
因为不小心把 id_rsa.pub 丢了,但是又不想改 id_rsa。。
```bash
ssh-keygen -y -f ~/.ssh/id_rsa > ~/id_rsa.pub
```

View File

@ -0,0 +1,33 @@
---
title: dB、dBm、dBw
createTime: 2022/08/01 15:05:48
tags:
categories:
- 随记
---
> 参考:中科院物理所[100 分钟看懂 dB、dBm、dBw 的区别](https://baijiahao.baidu.com/s?id=1722028647203360593)
- dB
$dB=10lg(\frac{P_1}{P_0})$
表示功率$P_1$相对于参考功率$P_0$的大小关系
常用的关系:+3dB表示功率增加为 2 倍;+10dB表示功率增加为 10 倍。-3dB表示功率减小为 1/2-10dB表示功率减小为 1/10。
对于电压、电流增益,系数变为 20
$A(I)(dB)=20lg(\frac{I_1}{I_0})$
$A(V)(dB)=20lg(\frac{V_1}{V_0})$
原因是:
$P=UI=I^2R=\frac{U^2}{R}$
- dBm、dBw
dBm、dBw 就是把 dB 公式中的参考功率$P_0$分别换成 1mW、1W
1 W = 30 dBm

View File

@ -0,0 +1,24 @@
---
title: office使用kms激活0x80080005问题
createTime: 2022/11/11 15:36:55
tags:
categories:
- 随记
---
> 参考[YerongAI/Office-Tool/Issues#216](https://github.com/YerongAI/Office-Tool/issues/216)
运行 `C:\WINDOWS\system32\SppExtComObj.exe` 如果异常会提示 `启动SppExtComObjHook.dll时出现问题`
检测注册表是否存在配置项 `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\SppExtComObj.exe`
若果存在,则将其删除
重新运行 `C:\WINDOWS\system32\SppExtComObj.exe`,如正常则会立刻返回 `exit with code 0`
重新使用 kms 激活工具激活即可
```bash
cscript "path for OSPP.VBS" /sethst:kms.ustc.edu.cn
cscript "path for OSPP.VBS" /act
```

View File

@ -0,0 +1,13 @@
---
title: 配置ssh免密登录
createTime: 2023/08/07 09:50:58
tags:
categories:
- 随记
---
机器 A 访问 机器 B
1. 在机器 A 上`ssh-keygen`
2. 把机器 A 用户目录下`.ssh`文件夹里`id_rsa.pub`的公钥复制到机器 B 用户目录下`.ssh`文件夹里`authorized_keys`

View File

@ -0,0 +1,58 @@
---
title: docker安装gitlab
createTime: 2022/02/19
tags:
- Docker
categories:
- 随记
---
## 安装
```bash
sudo docker pull gitlab/gitlab-ce
sudo docker run -d \\
--publish 1118:80 \\
--publish 1119:22 \\
--name texlab \\
--restart always \\
-v /home/yuany3721/mnt/gitlab/config:/etc/gitlab \\
-v /home/yuany3721/mnt/gitlab/logs:/var/log/gitlab \\
-v /home/yuany3721/mnt/gitlab/data:/var/opt/gitlab \\
--shm-size 256m \\
gitlab/gitlab-ce
```
## 修改配置文件
```bash
cd /home/yuany3721/mnt/gitlab/config
sudo vi gitlab.rb
# 找到external_url并修改为
external_url 'http://texlab.yuany3721.top'
# 找到gitlab_rails['gitlab_shell_ssh_port'\]并修改为
gitlab_rails['gitlab_shell_ssh_port'] = 1119
```
初始 root 的密码在`/home/yuany3721/mnt/gitlab/config/initial_root_password`
## 配置邮件
```bash
# 修改gitlab.rb
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.qq.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "XXXX@qq.com"
gitlab_rails['smtp_password'] = "123456" # qq授权码
gitlab_rails['smtp_domain'] = "smtp.qq.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = true
gitlab_rails['gitlab_email_from'] = "XXXX@qq.com" #和smtp_user_name一致,并且一定要有双引号
gitlab_rails['gitlab_email_enabled'] = true
```

View File

@ -0,0 +1,35 @@
---
title: dockerfile里修改pip和apt源
createTime: 2023/06/25 21:13:41
tags:
- Docker
categories:
- 随记
---
## apt
```dockerfile
RUN echo "deb https://mirrors.ustc.edu.cn/ubuntu jammy main restricted" > /etc/apt/sources.list && \
echo "deb https://mirrors.ustc.edu.cn/ubuntu jammy-updates main restricted" >> /etc/apt/sources.list && \
echo "deb https://mirrors.ustc.edu.cn/ubuntu jammy universe" >> /etc/apt/sources.list && \
echo "deb https://mirrors.ustc.edu.cn/ubuntu jammy-updates universe" >> /etc/apt/sources.list && \
echo "deb https://mirrors.ustc.edu.cn/ubuntu jammy multiverse" >> /etc/apt/sources.list && \
echo "deb https://mirrors.ustc.edu.cn/ubuntu jammy-updates multiverse" >> /etc/apt/sources.list && \
echo "deb https://mirrors.ustc.edu.cn/ubuntu jammy-backports main restricted universe multiverse" >> /etc/apt/sources.list && \
echo "deb https://mirrors.ustc.edu.cn/ubuntu jammy-security main restricted" >> /etc/apt/sources.list && \
echo "deb https://mirrors.ustc.edu.cn/ubuntu jammy-security universe" >> /etc/apt/sources.list && \
echo "deb https://mirrors.ustc.edu.cn/ubuntu jammy-security multiverse" >> /etc/apt/sources.list
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 871920D1991BC93C
# RUN rm -r /etc/apt/sources.list.d
```
## pip
```dockerfile
RUN mkdir -p /root/.pip
RUN echo "[global]" > /root/.pip/pip.conf && \
echo "index-url = https://pypi.mirrors.ustc.edu.cn/simple/" >> /root/.pip/pip.conf && \
echo "[install]" >> /root/.pip/pip.conf && \
echo "trusted-host=mirrors.ustc.edu.cn" >> /root/.pip/pip.conf
```

View File

@ -0,0 +1,59 @@
---
title: ubuntu安装docker engine
createTime: 2023/06/27 09:54:12
tags:
- docker
- Ubuntu
categories:
- 随记
---
对于无图形界面的 Ubuntu Server直接安装[Dokcer Engine](https://docs.docker.com/engine/install/ubuntu/)就可以。
1. 安装依赖
```bash
sudo apt update
sudo apt install ca-certificates curl gnupg
```
2. 配置 docker 的 GPG 密钥
```bash
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
```
3. 添加 Docker 的 apt 仓库
```bash
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```
4. 安装 Docker Engine
```bash
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 验证
docker version
docker compose version
# Hello World
sudo docker run hello-world
```
5. 配置国内镜像
```bash
vi /etc/docker/daemon.json
{
"registry-mirrors": ["http://hub-mirror.c.163.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn"]
}
sudo service docker restart
```

View File

@ -0,0 +1,16 @@
---
title: docker安装webdav
createTime: 2023/06/28 20:36:10
tags:
- Docker
categories:
- 随记
---
```bash
sudo docker pull ionelmc/webdav
sudo docker run --restart always --detach --name webdav --publish 7000:8080 \
--env WEBDAV_USERNAME=username --env WEBDAV_PASSWORD=password \
--env UID=$UID --volume /datadir:/media ionelmc/webdav
```

View File

@ -0,0 +1,18 @@
---
title: Docker换源
createTime: 2024/08/01 15:32:15
tags:
- Docker
categories:
- 随记
---
修改`/etc/docker/daemon.json`:
```bash
"registry-mirrors": [
"https://dockerhub.icu"
],
```
[https://github.com/dongyubin/DockerHub](https://github.com/dongyubin/DockerHub)

View File

@ -0,0 +1,52 @@
---
title: Docker自建Zerotier Planet
createTime: 2024/10/26 19:02:54
tags:
- ZeroTier
- Docker
categories:
- 随记
---
## 前言
在[ZeroTier 组网的简单应用](2024-07-01.md)中,我们自建了 Zerotier Moon并使用 Moon 优化了连接延迟。
但是在实际使用中,很多时候明明可以 ping 通 Moon 所在 IP但出现了断开连接的问题猜测可能原因是与 Planet 服务器连接不稳定,导致根本走不到 Moon 这一步,因此考虑自建 Planet 和 Controler。
## 卸载 Zerotier One 环境
由于[docker-zerotier-planet](https://github.com/xubiaolin/docker-zerotier-planet)使用容器化部署,为了避免端口冲突等问题,干脆把原来的 Zerotier-One 卸载掉:
```bash
sudo dpkg -P zerotier-one
sudo rm -rf /var/lib/zerotier-one/
```
## 配置 docker 环境
参考[ubuntu 安装 docker](../note/docker/2023-06-27.md)
## 配置 Planet
```bash
# 下载源码
git clone https://ghproxy.imoyuapp.win/https://github.com/xubiaolin/docker-zerotier-planet.git
# 执行安装脚本
cd docker-zerotier-planet
sudo ./deploy.sh
```
安装过程很安逸,按提示操作就完事了,安装结束后进入 web 页面新建网络、配置 ip 等操作与官方 Zerotier Controller 类似
## 客户端配置
### Windows
下载`planet`文件,覆盖到`C:\ProgramData\ZeroTier\One`
`Win+R` `services.msc`找到 Zerotier One重启服务然后就可以加入新建的网络了
### Linux
类似地,下载`planet`文件,覆盖到`/var/lib/zerotier-one`中,然后重启服务`sudo service zerotier-one restart`,重启好久可以加入网络了

View File

@ -0,0 +1,23 @@
---
title: windows下docker开放远程2375端口
createTime: 2025/03/17 15:25:38
tags:
- Docker
- Windows
categories:
- 随记
---
参考:[IBM Docker](https://www.ibm.com/docs/en/addi/6.1.0?topic=prerequisites-configuring-docker-engine-listen-tcp-socket)
1. 在 DockerDesktop 的 settings 中勾选`Expose daemon on tcp://localhost:2375 without TLS`
2. 在 docker engine 里添加`"hosts": ["tcp://0.0.0.0:2375"]`
3. `Apply & Restart`
4. 进 powershell 打开转发
```bash
netsh interface portproxy add v4tov4 listenport=2375 listenaddress=<your_IP> connectaddress=127.0.0.1 connectport=2375
```

View File

@ -0,0 +1,31 @@
---
title: Docker修改默认网段
createTime: 2025/03/27 22:20:49
tags:
- Docker
categories:
- 随记
---
修改`daemon.json`,加入以下配置:
```json
{
"default-address-pools": [
{
"base": "10.192.0.0/16",
"size": 22
}
]
}
```
还有个配置项是`bip`
```json
{
"bip": "192.168.5.1/24"
}
```
`bip`是修改 docker0 默认网桥的网段,`default-address-pools`则是修改所有的网络池

View File

@ -0,0 +1,74 @@
---
title: Docker安装Gitea
createTime: 2025/04/23 17:54:18
tags:
- Docker
categories:
- 随记
---
# Docker安装Gitea
使用 Docker Compose 快速部署 Gitea 代码托管平台。
## 配置文件
创建 `docker-compose.yml`
```yml
version: '3'
networks:
gitea:
external: false
services:
server:
image: docker.gitea.com/gitea:1.23.7
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- APP_NAME=Gitea for yuany3721
- DOMAIN=gitea.yuany3721.site
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=db:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=gitea
restart: always
networks:
- gitea
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- '7003:3000'
- '7005:22'
depends_on:
- db
db:
image: docker.io/library/postgres:14
restart: always
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=gitea
- POSTGRES_DB=gitea
networks:
- gitea
volumes:
- ./postgres:/var/lib/postgresql/data
```
## 使用说明
1. 保存配置文件到 `docker-compose.yml`
2. 运行 `docker-compose up -d` 启动服务
3. 访问 `http://your-domain:7003` 进入 Web 界面
## 端口说明
- **7003**: Web 界面端口
- **7005**: SSH 端口(用于 git 操作)

View File

@ -0,0 +1,354 @@
---
title: 使用Docker Compose构建MQTT消息记录服务
createTime: 2025/06/19 23:30:29
tags:
- Docker
categories:
- 随记
---
## 思路
使用两个Broker将主Broker消息单向桥接至存储Broker挂载一个中间件订阅存储Broker收到的所有消息并存储在数据库中。
## 实现
### 主Broker
`mosquitto.conf`
```ini
persistence true
persistence_location /mosquitto/data
log_dest file /mosquitto/log/mosquitto.log
listener 9001
port 1883
allow_anonymous true
connection mosquitto_storage
address mosquitto_storage:1883
topic # out 0
start_type automatic
```
### 存储Broker
`mosquitto.conf`
```ini
persistence true
persistence_location /mosquitto/data
log_dest file /mosquitto/log/mosquitto.log
listener 9001
port 1883
allow_anonymous true
```
### 数据库
`init.sh`
```bash
#!/bin/bash
psql -v ON_ERROR_STOP=1 --username "postgres" <<-EOSQL
CREATE DATABASE mqtt_data;
EOSQL
```
### 中间件
`main.py`
```python
import paho.mqtt.client as mqtt
import psycopg2
from psycopg2 import sql
import logging
import time
class Middleware:
def __init__(self, main_broker, storage_broker, db_name, db_user, db_password, db_host, db_port, blank_topic_name):
self.main_broker = main_broker
self.storage_broker = storage_broker
self.db_name = db_name
self.db_user = db_user
self.db_password = db_password
self.db_host = db_host
self.db_port = db_port
self.blank_topic_name = blank_topic_name
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler()
]
)
self.logger = logging.getLogger(__name__)
# 初始化数据库连接
self.postgres_conn = None
self.connect_to_database()
# 初始化MQTT客户端
self.storage_client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
self.storage_client.on_connect = self.on_connect
self.storage_client.on_message = self.on_message
self.storage_client.on_disconnect = self.on_disconnect
def connect_to_database(self):
"""连接到PostgreSQL数据库支持重试"""
max_retries = 5
retry_delay = 5 # 秒
for attempt in range(max_retries):
try:
self.postgres_conn = psycopg2.connect(
dbname=self.db_name,
user=self.db_user,
password=self.db_password,
host=self.db_host,
port=self.db_port
)
self.logger.info("Successfully connected to PostgreSQL database")
return
except psycopg2.OperationalError as e:
self.logger.warning(f"Database connection failed (attempt {attempt+1}/{max_retries}): {e}")
if attempt < max_retries - 1:
time.sleep(retry_delay)
retry_delay *= 2 # 指数退避
else:
self.logger.error("Failed to connect to database after multiple attempts")
raise
def start(self):
"""启动MQTT客户端并连接"""
try:
self.logger.info(f"Connecting to MQTT broker: {self.storage_broker}")
self.storage_client.connect(self.storage_broker, 1883, 60)
self.storage_client.loop_forever()
except Exception as e:
self.logger.error(f"Error in MQTT loop: {e}")
finally:
self.cleanup()
def on_connect(self, client, userdata, flags, reason_code, properties):
if reason_code.is_failure:
self.logger.error(f"Failed to connect to MQTT broker: {reason_code}")
return
self.logger.info(f"Connected to MQTT broker with code {reason_code}")
client.subscribe("#")
self.logger.info("Subscribed to all topics (#)")
def on_disconnect(self, client, userdata, reason_code):
if reason_code != 0:
self.logger.warning(f"Unexpected MQTT disconnection: {reason_code}")
# 尝试重新连接
time.sleep(5)
try:
client.reconnect()
except Exception as e:
self.logger.error(f"Reconnection failed: {e}")
def on_message(self, client, userdata, msg):
try:
payload = msg.payload.decode('utf-8')
self.logger.info(f"Received message from topic: {msg.topic}")
# 处理表名
topic_parts = msg.topic.split("/")
table_name = topic_parts[0] if topic_parts else self.blank_topic_name
table_name = table_name.replace("/", "_").replace(" ", "_").replace(".", "_")[:50] # 表名长度限制
# 分表
now = time.localtime()
year_month = f"{now.tm_year % 100:02d}{now.tm_mon:02d}"
table_name = f"{table_name}_{year_month}"
# 处理消息内容
if not payload.strip():
self.logger.warning(f"Empty payload received on topic: {msg.topic}")
return
self.store_message(table_name, msg.topic, payload)
except UnicodeDecodeError:
self.logger.error(f"Failed to decode message payload from topic: {msg.topic}")
except Exception as e:
self.logger.error(f"Error processing message: {e}")
def store_message(self, table_name, topic, payload):
"""将消息存储到数据库,尝试提取数值"""
cursor = None
try:
cursor = self.postgres_conn.cursor()
# 创建表(如果不存在),包含数值列
create_table_query = sql.SQL("""
CREATE TABLE IF NOT EXISTS {} (
id SERIAL PRIMARY KEY,
topic TEXT NOT NULL,
payload TEXT NOT NULL,
value NUMERIC,
timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW()
)
""").format(sql.Identifier(table_name))
cursor.execute(create_table_query)
# 尝试将payload转换为数值
value_num = None
try:
# 尝试直接转换为浮点数
value_num = float(payload)
self.logger.info(f"Payload converted to numeric value: {value_num}")
except (ValueError, TypeError):
# 转换失败保持为NULL
pass
# 插入数据
insert_query = sql.SQL("""
INSERT INTO {} (topic, payload, value)
VALUES (%s, %s, %s)
""").format(sql.Identifier(table_name))
cursor.execute(insert_query, (topic, payload, value_num))
self.postgres_conn.commit()
self.logger.info(f"Stored message in table '{table_name}'")
except psycopg2.InterfaceError:
self.logger.warning("Database connection lost, attempting to reconnect...")
self.connect_to_database()
except psycopg2.DatabaseError as e:
self.logger.error(f"Database error: {e}")
if cursor:
cursor.execute("ROLLBACK")
except Exception as e:
self.logger.error(f"Unexpected error: {e}")
if cursor:
cursor.execute("ROLLBACK")
finally:
if cursor:
cursor.close()
def cleanup(self):
"""清理资源"""
self.logger.info("Cleaning up resources...")
try:
if self.storage_client.is_connected():
self.storage_client.disconnect()
except Exception as e:
self.logger.error(f"Error disconnecting MQTT client: {e}")
try:
if self.postgres_conn and not self.postgres_conn.closed:
self.postgres_conn.close()
except Exception as e:
self.logger.error(f"Error closing database connection: {e}")
if __name__ == "__main__":
# 配置参数
MAIN_BROKER = "mosquitto_main"
STORAGE_BROKER = "mosquitto_storage"
DB_NAME = "mqtt_data"
DB_USER = "postgres"
DB_PASSWORD = "mosquitto"
DB_HOST = "postgresql"
DB_PORT = "5432"
BLANK_TOPIC_NAME = "blank_topic"
# 创建中间件实例并启动
middleware = Middleware(
main_broker=MAIN_BROKER,
storage_broker=STORAGE_BROKER,
db_name=DB_NAME,
db_user=DB_USER,
db_password=DB_PASSWORD,
db_host=DB_HOST,
db_port=DB_PORT,
blank_topic_name=BLANK_TOPIC_NAME
)
try:
middleware.start()
except KeyboardInterrupt:
middleware.logger.info("Shutting down by user request")
middleware.cleanup()
except Exception as e:
middleware.logger.error(f"Unexpected shutdown: {e}")
middleware.cleanup()
```
### Docker Compose
```yaml
services:
mosquitto_main:
image: eclipse-mosquitto
container_name: mosquitto_main
ports:
- 'custom_port:1883'
- 'custom_port:9001'
volumes:
- /custom_path/mosquitto/main_broker/config:/mosquitto/config
- /custom_path/mosquitto/main_broker/data:/mosquitto/data
- /custom_path/mosquitto/main_broker/log:/mosquitto/log
environment:
- TZ=Asia/Shanghai
restart: always
mosquitto_storage:
image: eclipse-mosquitto
container_name: mosquitto_storage
ports:
- 'custom_port:1883'
- 'custom_port:9001'
volumes:
- /custom_path/mosquitto/storage_broker/config:/mosquitto/config
- /custom_path/mosquitto/storage_broker/data:/mosquitto/data
- /custom_path/mosquitto/storage_broker/log:/mosquitto/log
environment:
- TZ=Asia/Shanghai
restart: always
postgresql:
image: postgres:latest
container_name: mosquitto_postgresql
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: mosquitto
PGDATA: /var/lib/postgresql/data/pgdata
TZ: Asia/Shanghai
ports:
- 'custom_port:5432'
volumes:
- /custom_path/mosquitto/postgresql/init.sh:/docker-entrypoint-initdb.d/init-db.sh
- postgresql_data:/var/lib/postgresql/data
restart: always
middleware:
image: python:3.10-slim
container_name: mqtt_middleware
volumes:
- /custom_path/mosquitto/middleware/requirements.txt:/requirements.txt
- /custom_path/mosquitto/middleware/main.py:/middleware.py
command: >
sh -c "pip install -i https://pypi.mirrors.ustc.edu.cn/simple --upgrade pip &&
pip install -i https://pypi.mirrors.ustc.edu.cn/simple -r /requirements.txt &&
python /middleware.py"
environment:
- TZ=Asia/Shanghai
depends_on:
- mosquitto_storage
- postgresql
restart: always
volumes:
postgresql_data:
driver: local
driver_opts:
type: none
o: bind
device: /data/mosquitto_postgresql_data
```
直接`docker compose up -d`拉起即可

View File

@ -0,0 +1,25 @@
---
title: gitpull提示stash
createTime: 2022/04/18
tags:
- git
categories:
- 随记
---
## Git: pull 时提示 Please commit your changes or stash them before you merge
1. 保留本地更改
```bash
git stash
git pull
git stash pop
```
2. 不保留本地更改
```bash
git reset --hard
git pull
```

View File

@ -0,0 +1,34 @@
---
title: gitignore
createTime: 2022/04/28
tags:
- git
categories:
- 随记
---
## .gitignore 相关规则
```bash
# 忽略所有.a结尾的文件
*.a
# 将lib.a除外
!lib.a
# 忽略项目根目录下的abc
/abc
# 忽略template目录下的所有文件注意是左斜杠
template/
```
## git 处理.gitignore 完成不了的工作
```bash
# 添加被.gitignore忽略的文件
git add -f abc.
# 删除已经提交过&&包含在.gitignore中的文件
git rm --cached logs/xx.log
# 目录
git rm --cached -r logs
# 如果提示某个文件无法忽略,可以添加-f强制忽略
git rm -f --cached logs/xx.log
```

View File

@ -0,0 +1,28 @@
---
title: git走代理
createTime: 2022/11/03 16:08:24
tags:
- git
categories:
- 随记
---
## 临时代理
```bash
git -c http.proxy=127.0.0.1:1080 clone http://xxxxxxx
```
## 永久代理
```bash
# socks
git config --global http.proxy 'socks5://127.0.0.1:1080'
git config --global https.proxy 'socks5://127.0.0.1:1080'
# http
git config --global http.proxy http://127.0.0.1:1080
git config --global https.proxy https://127.0.0.1:1080
# 对github.com单独配置代理
git config --global http.https://github.com.proxy socks5://127.0.0.1:1080
git config --global https.https://github.com.proxy socks5://127.0.0.1:1080
```

View File

@ -0,0 +1,20 @@
---
title: git远程仓库与本地建立联系失败refusing to merge unrelated histories
createTime: 2023/07/06 22:47:16
tags:
- git
categories:
- 随记
---
通常会出现在远端仓库有文件、本地仓库也有文件的时候,是因为这两个仓库在 sync 之前根本没有建立起来联系
## 解决方法 1
`git clone`远端仓库,然后把本地文件移动到下载的远端仓库中,再提交上去,相当于进行了一次对远端仓库的 commit
## 解决方法 2
强制合并:`git pull origin master --allow-unrelated-histories`
然后解决 conflict 再 push 回去,`git push origin local_main:remote_main`

View File

@ -0,0 +1,27 @@
---
title: github ssh timeout
createTime: 2024/01/21 20:00:26
tags:
- git
categories:
- 随记
---
[参考](https://github.com/orgs/community/discussions/88410#discussioncomment-8151064)
该方法需要先检查是否可以直接访问/通过代理访问 github
1. 在 `C:\Users\{username}\.ssh` 目录下创建 or 编辑 `config` 文件。
2. 将以下内容复制到 config
```ssh-config
Host github.com
User git
Hostname ssh.github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa
Port 443
```
3. 使用 `ssh -T git@github.com` 命令测试连接

View File

@ -0,0 +1,34 @@
---
title: git身份认证成功但public key permission denied
createTime: 2024/07/02 15:24:51
tags:
- git
categories:
- 随记
---
参考[Authenticated but can't fetch or push](https://github.com/orgs/community/discussions/27456)
`git pull`的时候,明明配置好了 ssh-key但仍然报错
```bash
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
```
首先使用`ssh -vT git@github.com`验证 ssh 和 public key 是不是正常的,如果返回内容中有:
```bash
Hi YourUserName! You've successfully authenticated, but GitHub does not provide shell access.
```
这样的内容,那说明 ssh 和 public key 配置没有问题。
可能导致这样问题的原因可能是 git 使用的内嵌 ssh而这个内嵌的 ssh 找不到我们配置的 rsa 密钥。
解决办法就是先卸载 git然后重新安装时注意选择`Use External OpenSSH`!
![external openssh](./extssh.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -0,0 +1,55 @@
---
title: Ubuntu设置屏幕分辨率及屏幕翻转
createTime: 2021/09/24
tags:
- Ubuntu
categories:
- 随记
---
> Version: Ubuntu 18.04.6 LTS
1. 使用`xrandr`查看屏幕信息
```txt
Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 8192 x 8192
VGA-0 connected primary 1920x1080+0+0 inverted (normal left inverted right x axis y axis) 0mm x 0mm
1024x768 60.00
800x600 60.32 56.25
848x480 60.00
640x480 59.94
1920x1080_60.00 59.96*
HDMI-0 disconnected (normal left inverted right x axis y axis)
```
这里的信息是修改后的内容,主要注意当前显示器名称,例如我的是 VGA-0
2. 获得分辨率详情
```bash
cvt 1920 1080
# 1920x1080 59.96 Hz (CVT 2.07M9) hsync: 67.16 kHz; pclk: 173.00 MHz
# Modeline "1920x1080_60.00" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync
```
注意输出中 Modeline 后的内容:"1920x1080_60.00"是 resolution 的名称,整个 Modeline 后所有信息是 newmode 所需信息
3. 设置并应用分辨率
```bash
xrandr --newmode "1920x1080_60.00" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync
xrandr --addmode VGA-0 "1920x1080_60.00"
```
4. 设置屏幕翻转
```bash
xrandr -o inverted
# left向左旋转90° right向右旋转90° normal正常显示
```
5. 设置开机自动配置
`~/.profile`中添加以上步骤中的命令
```bash
# set display resolution
cvt 1920 1080
xrandr --newmode "1920x1080_60.00" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync
xrandr --addmode VGA-0 "1920x1080_60.00"
# set display rotation
xrandr -o inverted
```

View File

@ -0,0 +1,27 @@
---
title: nginx+php上传文件配置
createTime: 2021/09/25
tags:
- linux
categories:
- 随记
---
- 设置`php.ini`
主要把包括的选项有:`post_max_size``upload_max_filesize``memory_limit``max_execution_time`
- 设置`nginx.conf`
主要是`client_max_body_size`,注意设置`sendfile on`
- nginx 一定程度上避免 502
```ini
location / {
......
    proxy_connect_timeout 300;
    proxy_send_timeout 300;
    proxy_read_timeout 300;
}
```

View File

@ -0,0 +1,23 @@
---
title: Ubuntu配置搜狗输入法
createTime: 2021/09/27
tags:
- Ubuntu
categories:
- 随记
---
> Version: Ubuntu 20.04.3 LTS
1. 下载 deb 包 [官网地址](https://pinyin.sogou.com/linux/)
2. ```bash
sudo dpkg -i sogoupinyin_版本号_amd64.deb
# 如果提示缺少依赖
sudo apt -f install
```
3. 设置系统语言
Settings --> Region & Language --> Manage Installed Languages
Keyboard input method system
设置为`fcitx`
4. 注销重新登录用户,使用 Ctrl+Space 即可切换为搜狗输入法

View File

@ -0,0 +1,50 @@
---
title: Ubuntu配置ssh和sftp
createTime: 2021/09/28
tags:
- Ubuntu
categories:
- 随记
---
## 安装
**ssh 是客户端sshd 才是服务端**
**2023-6-20 Update**: 在 Ubuntu22.04.2 中包名已经更新为`openssh-clien`, `openssh-server`, `openssh-sftp-server`
```bash
# 查看是否已经安装
dpkg -l | grep ssh
# 安装openssh server
sudo apt install openssh-server
```
## 修改端口
```bash
# 修改端口
sudo vi /etc/ssh/sshd_config
# 修改Port后的参数
# 重启ssh
sudo service ssh restart
```
- **远程连接**
```bash
ssh -p 修改后的端口 用户名@ip地址
```
## 配置 sftp
```bash
# 使用系统自带的internal-sftp服务
sudo vi /etc/ssh/sshd_config
# 修改以下字段
Subsystem sftp internal-sftp
# 限定用户
Match Group sftp
# 更改登录后默认路径
ChrootDirectory /
```

View File

@ -0,0 +1,26 @@
---
title: Ubuntu防火墙操作
createTime: 2021/09/28
tags:
- Ubuntu
categories:
- 随记
---
```bash
# 启用防火墙
sudo ufw enable
# 查看防火墙状态
sufo ufw status
# 默认拒绝连接
sudo ufw default deny
# 开启端口
sudo ufw allow 1234
# 开启指定协议的端口
sudo ufw allow 8001/tcp
# 删除规则
sudo ufw delete allow 1234
sudo ufw delete allow 8081/tcp
# 重新加载配置
sudo ufw reload
```

View File

@ -0,0 +1,35 @@
---
title: Ubuntu配置阿里云ddns
createTime: 2021/09/29
tags:
- Ubuntu
categories:
- 随记
---
1. 生成阿里云 access key **注意:不能使用 ram 子用户**
2. 下载并配置 ddns
```bash
curl https://github.com/NewFuture/DDNS/releases/download/v2.10.2/ddns -#SLo ddns && chmod 777 ddns
# 自动生成config.json
./ddns -h
# 配置config.json
vi config.json
```
3. 使用 ddns 配置
```bash
./ddns -c config.json
```
~~我自己在配置时发现,如果同时解析 ipv4 和 ipv6 时,阿里云的 ipv6 优先级要高于 ipv4但是截至 CST+8 21.09.30 ipv6 连接体验仍然不尽如人意,所以可以只解析 ipv4~~
4. 用 crontab 设置每小时自动更新 ddns
````bash
crontab -e
# 设置每小时的30min自动更新
30 \* \* \* \* date >> path/to/ddns.log
30 \* \* \* \* path/to/./ddns -c path/to/config.json >> path/to/ddns.log
# 查看crontab设置
crontab -l
```
````

View File

@ -0,0 +1,12 @@
---
title: ubuntu设置时区
createTime: 2021/09/30
tags:
- Ubuntu
categories:
- 随记
---
`sudo dpkg-reconfigure tzdata`
Asia --> Shanghai

View File

@ -0,0 +1,14 @@
---
title: Ubuntu startup设置开机自启命令
createTime: 2021/09/30
tags:
- Ubuntu
categories:
- 随记
---
> Version: Ubuntu Server 20.04.3 LTS
1. 建立自己的脚本,如`wlt.sh`
2. 修改脚本执行权限`chmod 775 wlt.sh`
3. 将脚本放入`/etc/profile.d`路径下即可 `/etc/init.d update-rc.d wlt.sh defaults 91`

View File

@ -0,0 +1,87 @@
---
title: Ubuntu配置mariadb
createTime: 2021/09/30
tags:
- Ubuntu
categories:
- 随记
---
## 安装
`sudo apt install mariadb-server`
## 配置
```bash
# 启动 状态 重启
sudo service mysql start
service mysql status
sudo service mysql restart
# 初始化配置
sudo mysql_secure_installation
# 修改配置
sudo vi mariadb.cnf
# 端口号
Port 1234
# 允许远程连接登录
bind-address = 0.0.0.0
```
## 修改用户
```sql
# 修改用户host
update user set host = '%' where user = 'root';
# 允许密码登录
update user set plugin='mysql\_native\_password' where user='root';
update user set password=password('password') where user='root';
# 修改密码
ALTER user 'root'@'localhost' IDENTIFIED BY 'passward';
# 用户授权
grant all privileges on \*.\* to 'user'@'host' identified by 'password' with grant option;
# 添加权限(和已有权限合并,不会覆盖已有权限)
GRANT Insert ON 'your database'.\* TO 'user'@'host';
# 删除权限
REVOKE Delete ON 'your database'.\* FROM 'user'@'host';
# 查看权限
show grants for 'user'@'localhost';
# 回收权限
revoke create on \*.\* from 'user@localhost';
# 删除用户
drop user 'user'@'localhost';
# 重命名用户
rename user 'user'@'%' to 'user1'@'%';
```
权限列表:
![MySQL权限列表](./img/Pasted-7.png)
## 解决 ERROR 1698 (28000)
```bash
sudo vi mysqld.cnf
```
加入以下字段
```ini
[mysqld]
skip-grant-tables
```
```bash
# 重启mysql服务
sudo service mysql restart
# 直接enter进mysql
mysql -u root -p
```
Ubuntu 的日志在`/var/log/mysql`
```sql
use mysql
update user set authentication_string=password("password"),plugin='mysql_native_password' where user='root';
flush privileges;
quit
```

View File

@ -0,0 +1,16 @@
---
title: ubuntu下多版本openjdk配置
createTime: 2022/05/11
tags:
- Ubuntu
categories:
- 随记
---
```bash
sudo apt install openjdk-8-jdk
sudo apt install openjdk-1-jdk
# ...
# 选择java版本
sudo update-alternatives --config java
```

View File

@ -0,0 +1,47 @@
---
title: Ubuntu设置swap分区
createTime: 2022/11/02 16:22:28
tags:
- Ubuntu
categories:
- 随记
---
**通常Ubuntu Server 安装完成后已经自动配置了 swap 分区,使用`sudo swapon --show`或者`free -m`查看**
```bash
# 建立swapfile
sudo fallocate -l 4G /swap.img
# 设置权限
sudo chmod 600 /swap.img
# 配置分区生效
sudo mkswap /swap.img
sudo swapon /swap.img
# sudo cp /etc/fstab /etc/fstab.bak
echo '/swap.img none swap sw 0 0' | sudo tee -a /etc/fstab
# 查看分区生效情况
# sudo swapon --show
# free -m
```
分区大小参考:
| RAM(GB) | No hibernation | With Hibernation | Maximum |
| ------- | -------------- | ---------------- | ------- |
| 1 | 1 | 2 | 2 |
| 2 | 1 | 3 | 4 |
| 3 | 2 | 5 | 6 |
| 4 | 2 | 6 | 8 |
| 5 | 2 | 7 | 10 |
| 6 | 2 | 8 | 12 |
| 8 | 3 | 11 | 16 |
| 12 | 3 | 15 | 24 |
| 16 | 4 | 20 | 32 |
| 24 | 5 | 29 | 48 |
| 32 | 6 | 38 | 64 |
| 64 | 8 | 72 | 128 |
| 128 | 11 | 139 | 256 |
| 256 | 256 | 512 | 512 |
| 512 | 512 | 1024 | 1024 |
| 1024 | 1024 | 2048 | 2048 |

View File

@ -0,0 +1,25 @@
---
title: ssh config
createTime: 2022/11/03 16:08:27
tags:
- ssh
categories:
- 随记
---
编辑`~/.ssh/config`文件
文件格式:
```ssh-config
Host hostalias # 关键词
HostName example.com or ip addr # 主机地址
User root # 用户名
IdentityFile ~/.ssh/id_rrrsa # 认证文件
Port 22 # 端口
ProxyCommand command # 代理命令
```
可以使用`ssh hostalias`替代后面一堆配置选项
没有指定 hostname 的 IdentityFile 默认还是去 id_rsa 做对应

View File

@ -0,0 +1,58 @@
---
title: apt换源
createTime: 2023/01/10 14:54:26
tags:
- Ubuntu
categories:
- 随记
---
1. 查看 codename
```bash
lsb_release -a
```
```text
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.5 LTS
Release: 20.04
Codename: focal
```
2. 换源
```bash
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
sudo vi /etc/apt/sources.list
```
**注意这里 codename 的对应关系**
```sources.list
deb https://mirrors.ustc.edu.cn/ubuntu/ focal main restricted universe multiverse
deb https://mirrors.ustc.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
deb https://mirrors.ustc.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
deb https://mirrors.ustc.edu.cn/ubuntu/ focal-security main restricted universe multiverse
deb https://mirrors.ustc.edu.cn/ubuntu/ focal-proposed main restricted universe multiverse
deb-src https://mirrors.ustc.edu.cn/ubuntu/ focal main restricted universe multiverse
deb-src https://mirrors.ustc.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
deb-src https://mirrors.ustc.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
deb-src https://mirrors.ustc.edu.cn/ubuntu/ focal-security main restricted universe multiverse
deb-src https://mirrors.ustc.edu.cn/ubuntu/ focal-proposed main restricted universe multiverse
```
```bash
# 如果报错 NO_PUBKEY ABCDE12345
sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com ABCDE12345
```
3. 更新
```bash
sudo apt update
sudo apt upgrade
```
> ubuntu 安装时的 mirror 选择:`https://mirrors.ustc.edu.cn/ubuntu`

View File

@ -0,0 +1,33 @@
---
title: Certbot配置nginx中ssl访问
createTime: 2023/05/08 13:00:12
tags:
- linux
- certbot
categories:
- 随记
---
`Ubuntu 22.04.01 LTS`为例
1. 安装 certbot
```bash
sudo apt list | grep certbot
sudo apt install certbot
sudo apt install python3-certbot-nginx
```
2. 配置 ssl 证书
```bash
sudo certbot --nginx
```
3. 配置自动更新证书
```bash
crontab -e
```
三个月更新一次:`0 0 1 3,6,9,12 * sudo certbot renew --force-renewal`

View File

@ -0,0 +1,107 @@
---
title: Ubuntu Server基本配置
createTime: 2023/06/20 21:10:07
tags:
- ubuntu
categories:
- 随记
---
## 配置联网超时
> 启动时卡在`A start job is running for wait for network to be Configured`
进入目录`/etc/systemd/system/network-online.target.wants`修改配置文件`systemd-networkd-wait-online.service`
在[Service]下添加`TimeoutStartSec=2sec`设置超时时间为 2 秒:
```bash
[Service]
Type=oneshot
ExecStart=/lib/systemd/systemd-networkd-wait-online
RemainAfterExit=yes
TimeoutStartSec=2sec
```
## 配置 swap 分区
参考[Ubuntu 设置 swap 分区](./2022-11-02.html)
## 挂载数据盘
1. 使用`df -h`命令查看磁盘信息,没有就是未挂载。
2. 格式化与分区:
```bash
# 查看分区信息
sudo fdisk -l
# 磁盘格式化/分区
sudo fdisk /dev/sdabcd
# 一些基本命令m菜单 p打印分区 d删除分区 n新建分区 w保存并退出
# 格式化分区
sudo mkfs -t ext4 /dev/sdabcd
```
3. 挂载:
```bash
# 挂载
sudo mkdir /data
sudo mount /dev/sdabcd /data
```
4. 启动自动挂载:
```bash
# 查看UUID
blkid
# 修改
sudo vi /etc/fstab
# UUID=对应的UUID /data ext4 defaults 0 1
# 检查配置文件是否有误
sudo mount -a
```
## 配置 OpenSSH
参考[Ubuntu 配置 ssh 和 sftp](./2021-09-28-88168a.md)
## 连接 wifi
1. `ip a`查看网络设备信息
2. 编辑 netplan 配置文件
```bash
# 查看原有配置文件目录
ls /etc/netplan
# 如果没有则生成一个新的配置文件
# netplan generate
# 编辑配置文件
sudo vi /etc/netplan/xxx.yaml
# 添加wifi配置
network:
version: ****
wifis:
wifi设备名:
access-points:
wifi_ssid:
password: ****
dhcp4: true
# 保存后验证(验证通过并应用)
sudo netplan try
# 应用
# sudo netplan apply
# 查看网络信息
ip addr
```
连接成功后随便 ping 一个测试一下
3. `sudo apt install net-tools`(可选)
## 一些小问题
1. 使用独立显卡输出,安装系统屏幕显示多次卡在不一样的位置,通常是因为安装程序不带独显驱动,使用集显输出或 IPMI 远程安装即可

View File

@ -0,0 +1,17 @@
---
title: Ubuntu设置时区
createTime: 2023/06/24 18:55:29
tags:
- Ubuntu
categories:
- 随记
---
```bash
# 查看时区列表
timedatectl list-timezones | grep Shanghai
# 设置时区
sudo timedatectl set-timezone Asia/Shanghai
# 查看时间
date
```

View File

@ -0,0 +1,21 @@
---
title: bash脚本格式问题
createTime: 2023/06/26 12:11:42
tags:
- linux
categories:
- 随记
---
运行 bash 脚本时报错`-bash: ./create-lxc-template.bash: /bin/bash^M: bad interpreter: No such file or directory`
这个错误通常是由于在 Windows 环境下编辑的脚本文件,其中包含了 Windows 特有的换行符CRLF即“\r\n”而不是 Unix/Linux 环境使用的换行符LF即“\n”
使用`sed -i 's/\r//' file.bash`将文件中的 CRLF 替换为 LF。您可以使用以下命令将文件中的 CRLF 替换为 LF
也可以使用 dos2unix 工具将文件转换为 Unix 格式。可以使用 dos2unix 工具将文件从 Windows 格式转换为 Unix 格式。如果您的系统中没有安装 dos2unix 工具,请使用以下命令安装:
```bash
sudo apt install dos2unix
dos2unix file.bash
```

View File

@ -0,0 +1,36 @@
---
title: ubuntu安装图形界面并按需启动
createTime: 2023/06/29 00:28:24
tags:
- ubuntu
categories:
- 随记
---
1. 安装图形界面和 xrdp
```bash
sudo apt install ubuntu-desktop
sudo apt install xrdp
# 开启xrdp端口
sudo ufw allow 3389/tcp
sudo ufw reload
```
2. 将默认启动方式修改为命令行
```bash
sudo systemctl set-default multi-user.target
sudo systemctl disable gdm
sudo systemctl disable xrdp
# 查看默认启动方式
systemctl get-default
# graphical.target是图形界面multi-user.target是多用户命令行界面
```
3. 启动图形界面和 xrdp
```bash
sudo systemctl start gdm # 返回命令行界面需要stop一下
sudo systemctl start xrdp
```

View File

@ -0,0 +1,68 @@
---
title: 回退Ubuntu Linux kernel
createTime: 2024/09/04 17:57:37
tags:
- ubuntu
categories:
- 随记
---
## 背景
前段时间 Ubuntu22.4 自动更新内核后nvidia 535.86 安装不上了,编译报错`ERROR: modpost: GPL-incompatible module nvidia.ko uses GPL-only symbol 'rcu_read_unlock_strict'`
大概有这么个公告:
> **Problem with 535 Nvidia drivers and 5.15.0-106 kernel**
> Recently, an ubuntu update to the 5.15.0-106 kernel produced the following error from the nvidia driver when it compiled the kernel module:
>
> ERROR: modpost: GPL-incompatible module nvidia.ko uses GPL-only symbol 'rcu_read_unlock_strict'
>
> We typically freeze our driver updates so that we can do them at planned downtimes the fix was to unhold the held nvidia-driver packages and upgrade to nvidia-driver-550
在 forum 上也确定了确实是内核更新带来的 bug所以简单粗暴回退内核更新尝试解决
## 回退 kernel
```bash
# 查看当前内核版本
uname -a
# 查看grub可选内核版本
grep menuentry /boot/grub/grub.cfg
```
输出类似下面这样:
> if [ x"${feature_menuentry_id}" = xy ]; then
> menuentry_id_option="--id"
> menuentry_id_option=""
> export menuentry_id_option
> menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-cdc0eb43-b3e9-4337-b245-bb62aeb7cff5' {
> submenu 'Advanced options for Ubuntu' $menuentry_id_option 'gnulinux-advanced-cdc0eb43-b3e9-4337-b245-bb62aeb7cff5' {
> menuentry 'Ubuntu, with Linux 5.15.0-119-generic' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.15.0-119-generic-advanced-cdc0eb43-b3e9-4337-b245-bb62aeb7cff5' {
> menuentry 'Ubuntu, with Linux 5.15.0-119-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.15.0-119-generic-recovery-cdc0eb43-b3e9-4337-b245-bb62aeb7cff5' {
> menuentry 'Ubuntu, with Linux 5.15.0-105-generic' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.15.0-105-generic-advanced-cdc0eb43-b3e9-4337-b245-bb62aeb7cff5' {
> menuentry 'Ubuntu, with Linux 5.15.0-105-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.15.0-105-generic-recovery-cdc0eb43-b3e9-4337-b245-bb62aeb7cff5' {
> menuentry 'Ubuntu, with Linux 5.15.0-84-generic' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.15.0-84-generic-advanced-cdc0eb43-b3e9-4337-b245-bb62aeb7cff5' {
> menuentry 'Ubuntu, with Linux 5.15.0-84-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.15.0-84-generic-recovery-cdc0eb43-b3e9-4337-b245-bb62aeb7cff5' {
> menuentry 'Ubuntu, with Linux 5.15.0-78-generic' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.15.0-78-generic-advanced-cdc0eb43-b3e9-4337-b245-bb62aeb7cff5' {
> menuentry 'Ubuntu, with Linux 5.15.0-78-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.15.0-78-generic-recovery-cdc0eb43-b3e9-4337-b245-bb62aeb7cff5' {
> menuentry 'UEFI Firmware Settings' $menuentry_id_option 'uefi-firmware' {
说明可选内核版本有`Ubuntu, with Linux 5.15.0-119-generic``Ubuntu, with Linux 5.15.0-105-generic``Ubuntu, with Linux 5.15.0-84-generic``Ubuntu, with Linux 5.15.0-78-generic`
```bash
# 查看nvidia驱动版本匹配
ls /var/lib/dkms/nvidia/
# 修改GRUB文件
sudo vi /etc/default/grub
```
修改`GRUB_DEFAULT=0``0`值为`"Advanced options for Ubuntu>合适的内核版本"`
```bash
# 更新grub
sudo update-grub
# 重启
sudo reboot
```

View File

@ -0,0 +1,40 @@
---
title: 使用zfs存储池的lxc容器扩容
createTime: 2024/12/24 08:59:05
tags:
- ubuntu
categories:
- 随记
---
```bash
# 查看容器硬盘空间
df -h
# 类似于 lxd-pool/containers/container_name 36G 35G 1.9G
# 在宿主机中查看zfs存储池信息
lxc storage list
lxc storage info lxc-zfs-pool-name
```
如果是 zfs 空间不足,则扩容 zfs
```bash
sudo zpool set autoexpand=on lxc-zfs-pool-name
# 扩容存储池文件
# 如果是apt安装ZFS存储文件通常位于/var/lib/lxd/disks/default.img如果是snap安装则位于/var/snap/lxd/common/lxd/disks/default.img。
sudo truncate -s +20G /var/lib/lxd/disks/default.img
# 重启lxd
sudo service lxd restart # apt安装
sudo systemctl restart snap.lxd.daemon # snap安装
```
如果是容器配额不足zfs 有空间,容器空间满了),修改容器配额:
```bash
# 查看容器配额
zfs get quota lxc-zfs-pool-name/containers/container-name
# 增加容器配额
zfs set quota=newsize(例如80G) lxc-zfs-pool-name/containers/container-name
```
不需要重启容器,实时生效

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

@ -0,0 +1,30 @@
---
title: micropython + vscode配置ESP32开发环境
createTime: 2023/06/05 16:37:09
tags:
- esp32
categories:
- 随记
---
1. 准备工作
下载[micropython for esp32](https://micropython.org/download/esp32/)
vscode 安装插件“Pymakr”
2. 烧写 micropython
```bash
pip install esptool
esptool --chip esp32 --port your_serial_port clear_flash
esptool --chip esp32 --port your_serial_port write_flash -z 0x1000 your_micropython.bin
```
3. 在 Pymakr 中新建项目,选择同步目录,选择 create terminal出现 micropython 命令行即为配置成功
![pymakr](./img/pymakr.png)
![pymakr](./img/pymakr_terminal.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -0,0 +1,22 @@
---
title: python依赖固化
createTime: 2022/04/17
tags:
- Python
categories:
- 随记
---
## 生成 requirements.txt
```bash
pipreqs . --encoding=utf8 --force
```
如果使用`pip freeze > requirements.txt`会把当前环境中所有包全列入其中,如果项目运行在单个虚拟环境中时可以使用
## 安装
```bash
pip install -r requirements.txt
```

View File

@ -0,0 +1,34 @@
---
title: 修改pip源
createTime: 2022/10/19 16:34:09
tags:
- python
categories:
- 随记
---
1. 临时换源
```powershell
pip install xxx -i https://pypi.mirrors.ustc.edu.cn/simple/
```
2. 永久换源
```powershell
pip config set global.index-url https://pypi.mirrors.ustc.edu.cn/simple/
```
也可以修改配置文件linux 在`~/.pip/pip.conf`Windows 在`C:\Users\YourUserName\AppData\Roaming\pip\pip.ini`,内容为:
```ini
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
```
> 常用源
> 中国科学技术大学 https://pypi.mirrors.ustc.edu.cn/simple/
> 清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
> 阿里云 https://mirrors.aliyun.com/pypi/simple/
> 豆瓣 https://pypi.douban.com/simple/
> 华中科技大学 https://pypi.hustunique.com/

View File

@ -0,0 +1,30 @@
---
title: python虚拟环境配置
createTime: 2024/07/31
tags:
- python
categories:
- 随记
---
1. Ubuntu
```bash
# 新建虚拟环境
python -m venv venv_name
# 激活虚拟环境
source venv_name/bin/activate
# 停用虚拟环境
deactivate
```
2. Windows
```bash
# 新建虚拟环境
python -m venv venv_name
# 激活虚拟环境
venv_name/Scripts/activate
# 停用虚拟环境
deactivate
```

View File

@ -0,0 +1,29 @@
---
title: win10多版本openjdk配置
createTime: 2022/04/24
tags:
- Windows
categories:
- 随记
---
# 生成 jre
打开管理员权限的 cmd
```powershell
bin\jlink.exe --module-path jmods --add-modules java.desktop --output jre
```
## 配置路径
```text
JAVA_HOME : %JAVA11_HOME%
JAVA8_HOME : C:\Program Files\Java\jdk-8
JAVA11_HOME : C:\Program Files\Java\jdk-11
JAVA17_HOME : C:\Program Files\Java\jdk-17
CLASSPATH : .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;
PATH : .;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
```
切换版本时只需改`JAVA_HOME`后面的指向即可

View File

@ -0,0 +1,31 @@
---
title: win10配置maven
createTime: 2022/04/24
tags:
- Windows
categories:
- 随记
---
## 配置 PATH
```text
MAVEN_HOME : C:\Program Files\Maven
PATH : .;%MAVEN_HOME%\bin;
```
## 配置 repo 和国内源
修改 settings.xml
```xml
# 配置本地仓库settings标签中
<localRepository>C:\Program Files\Maven\repo</localRepository>
# 配置阿里云镜像在mirros标签中配置子标签
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
```

View File

@ -0,0 +1,40 @@
---
title: win10配置gradle
createTime: 2022/04/25
tags:
- Windows
categories:
- 随记
---
## 配置 PATH
## 修改默认缓存目录
```powershell
gradle -g C:\Program Files\Gradle\.gradle
```
这个错误 `Failed to load native library 'native-platform.dll' for Windows 10 amd64.` 是因为权限不够
## 配置国内源
在默认缓存目录下新建 init.gradle 文件
```ini
allprojects {
repositories {
def ALIYUN_REPOSITORY_URL = 'https://maven.aliyun.com/repository/public'
all { ArtifactRepository repo ->
if(repo instanceof MavenArtifactRepository){
def url = repo.url.toString()
if (url.startsWith('https://repo1.maven.org/maven2')) {
project.logger.lifecycle "Repository replaced by ALIYUN_REPOSITORY_URL."
remove repo
}
}
}
maven { url ALIYUN_REPOSITORY_URL }
}
}
```

View File

@ -0,0 +1,28 @@
---
title: powershell修改提示中文件路径
createTime: 2022/05/18 21:18:57
tags:
- Windows
categories:
- 随记
---
参考[hiding-the-full-file-path-in-a-powershell-command-prompt-in-vscode](https://stackoverflow.com/questions/52107170/hiding-the-full-file-path-in-a-powershell-command-prompt-in-vscode)
1. `test-path $profile` (is there a profile set up?)
2. `new-item -path $profile -itemtype file -force` (assuming the answer to the above is false)
3. `notepad $profile` (opens notepad)
4. paste in (from the SuperUser answer above)
```powershell
function prompt {
$p = Split-Path -leaf -path (Get-Location)
"$p> "
}
```
5. save (you shouldn't have to chose a location, it is already done for you)
> 这里其实直接新开一个 powershell 窗口就可以了
6. reload vscode - you will probably get an error message about running scripts (or just do next step before reload)
7. `Set-ExecutionPolicy RemoteSigned -Scope CurrentUser` (at your integrated terminal PS prompt, also from the SuperUser answer)
8. reload vscode

View File

@ -0,0 +1,49 @@
---
title: 使用nssm注册glances为服务运行
createTime: 2025/03/14 22:24:23
tags:
- Windows
categories:
- 随记
---
1. 下载 nssm
[https://nssm.cc/download](https://nssm.cc/download)
解压相应的 nssm.exe 到目录
2. 配置运行环境
```bash
# 安装环境
python -m venv venv
pip install glances fastapi uvicorn jinja2
# docker支持
pip install glances[containers]
# 测试环境
path/to/venv/Scripts/python.exe -m glances --bind 127.0.0.1 --port 8080 -w -q
```
3. 配置 nssm
```bash
.\nssm.exe install glances
```
在对话框中配置:
Path: `path/to/venv/Scripts/python.exe`
Startup Directory: `path/to/venv/Scripts/`
Augments: `-m glances --bind 127.0.0.1 --port 8080 -w -q`
4. 启动服务
```bash
.\nssm.exe start glances
```
5. 设置服务延迟启动
```bash
nssm set glances start SERVICE_DELAYED_AUTO_START
```

View File

@ -0,0 +1,14 @@
---
title: Windows PowerShell 在此系统上禁止运行脚本
createTime: 2025/03/14 22:05:52
tags:
- Windows
categories:
- 随记
---
Windows PowerShell 无法加载文件 xxx.ps1因为在此系统上禁止运行脚本
```bash
set-executionpolicy remotesigned
```

View File

@ -0,0 +1,14 @@
---
title: WordPress增加未分类类别查询
createTime: 2021/09/10
tags:
- Wordpress
categories:
- 随记
---
在主题编辑器中找到分类目录页面,添加如下代码:
```php
<h2><a href="<?php echo home_url()?>/archives/category/uncategorized">未分类</a></h2>
```

View File

@ -0,0 +1,91 @@
---
title: 为WordPress创建子主题
createTime: 2021/09/16
tags:
- Wordpress
categories:
- 随记
---
## 子主题
- 父主题是一个完整的主题,其中包括所有必需的 WordPress 模板文件和主题工作所需的文件资源。所有主题(不包括子主题)都可以被认为是父主题。
- 子主题可以继承父主题所有功能和外观,但可用于对主题的任何部分进行修改。自定义子主题与父主题的文件是分开的,升级父主题时不会影响对站点所做的修改。
**如果需要进行大量的样式、功能修改,则不推荐使用子主题**
## 创建子主题
找到`wp-content/themes`,记住父主题的**文件夹名称(注意不是主题名)**,这里以 kratos 为例。
1. 在 temes 目录下新建文件夹并进入,文件夹即为子主题路径。
```bash
mkdir kratos-yuany3721
cd kratos-yuany3721
```
2. 新建`style.css`文件并进行配置如下:
```css
/*
Theme Name: kratos-yuany3721
Theme URI: http://example.com
Description: kratos-yuany3721
Author: yuany3721
Author URI: http://example.com
Template: kratos
Version: 0.0.1
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Tags: light, dark, two-columns, right-sidebar, responsive-layout, accessibility-ready
Text Domain: yyyy
*/
```
其中Theme Name 需要对 themes 目录内主题唯一Template 后写的是父主题的**文件夹名称**,其余各内容均非必填项。
3. 新建`functions.php`并进行配置。回到父主题查看`functions.php`
- 如果存在 get_template 函数,例如 get_template_directory()或者 get_template_directory_uri(),则如下配置 functions.php
```php
<?php
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_styles' );
function my_theme_enqueue_styles() {
wp_enqueue_style( 'child-style', get_stylesheet_uri(),
array( 'parenthandle' ),
wp_get_theme()->get('Version') // this only works if you have Version in the style header
);
}
```
- 如果存在 get_stylesheet 函数,例如 get_stylesheet_directory()或 get_stylesheet_directory_uri(),则如下配置 functions.php
```php
<?php
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_styles' );
function my_theme_enqueue_styles() {
$parenthandle = 'parent-style'; // This is 'twentyfifteen-style' for the Twenty Fifteen theme.
$theme = wp_get_theme();
wp_enqueue_style( $parenthandle, get_template_directory_uri() . '/style.css',
array(), // if the parent theme code has a dependency, copy it to here
$theme->parent()->get('Version')
);
wp_enqueue_style( 'child-style', get_stylesheet_uri(),
array( $parenthandle ),
$theme->get('Version') // this only works if you have Version in the style header
);
}
```
- 以本文 kratos 为例,配置如下:
```php
<?php
function my_theme_enqueue_styles() {
wp_enqueue_style( 'child-style', get_template_directory_uri().'/style.css' );
}
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_styles');
```
4. 回到 WordPress 主题中查看,如果配置无误就会出现一个新的子主题,点击启用即可

View File

@ -0,0 +1,10 @@
---
title: WordPress开启debug模式
createTime: 2021/09/27
tags:
- Wordpress
categories:
- 随记
---
找到 WordPress 根目录下`wp-config.php`文件,找到`WP_DEBUG`字段改为 true增加`WP_DEBUG_DISPLAY`字段并设置为 true

View File

@ -0,0 +1,85 @@
---
title: WordPress全部文章分类页面
createTime: 2021/09/30
tags:
- Wordpress
categories:
- 随记
---
1. 复制一个 page.php 为 catlist.php
```bash
cd usr/wordpress # 自己的WordPress目录
find . -name page.php # 找到自己主题对应的路径
cd YourThemePath
cp page.php catlist.php
```
2. 在 catlist.php 最前添加代码
```php
<?php
/*
Template Name: Category
*/
?>
```
3. 在 catlist.php 中找到`<?php the_content();?>`并在其后添加如下代码
```php
<?php
//获得顶级分类
$taxonomies=get_terms('category',array('hide_empty'=>false,'parent'=>'0',));
if(!empty($taxonomies)){
foreach($taxonomies as $category){
if($category->name != '未分类'){?>
<h2><a href=<?php echo get_category_link($category->term_id)?>><?php echo $category->name?></a></h2>
<?php
echo '<ul>';
//获取二级分类
$cats=get_terms('category',array('hide_empty'=>false,'parent'=>$category->term_id,));
if(!empty($cats)){
foreach($cats as $cat){?>
<h3><a href=<?php echo get_category_link($cat->term_id)?>><?php echo $cat->name?></a></h3>
<?php
echo '<ul>';
//获取三级分类
$terms = get_terms('category',array('hide_empty'=>false,'parent'=>$cat->term_id,));
if(!empty($terms)) {
foreach($terms as $term){?>
<h4><a href=<?php echo get_category_link($term->term_id)?>><?php echo $term->name?></a></h4>
<?php
}
}
echo '</ul>';
}
}
echo '</ul>';
}
}
}
?>
<h2><a href="<?php echo home_url()?>/archives/category/uncategorized">未分类</a></h2>
<style>
h2>a,
h3>a,
h4>a {
color: black;
}
h2 {
margin-top: 2em;
font-size: 28px;
}
h3 {
font-size: 22px;
}
h4 {
font-size: 18px;
}
</style>
```
4. 保存模板,新建空白页面,页面模板选第二步 Template Name 后的名字,这里是 Category
5. 保存并发布,在菜单添加该页面即可

View File

@ -0,0 +1,28 @@
---
title: 用vite构建的vue3+ts中按需使用element-plus组件API
createTime: 2022/05/29 23:45:27
tags:
- Vue
categories:
- 随记
---
参考[manually-import](https://element-plus.org/en-US/guide/quickstart.html#manually-import)
官方给的 warning 用 js 给出了解决方案:
> You need to manually import the styles if you're using unplugin-element-plus and only used the component API.
>
> Example:
>
> ```js
> import { ElMessage } from 'element-plus'
> import 'element-plus/es/components/message/style/css'
> ```
这个 css 路径在 ts 的 element-plus 中不一样,路径变成了`element-plus/lib/theme-chalk/`,所以需要这样引入:
```ts
import { ElMessage } from 'element-plus'
import 'element-plus/lib/theme-chalk/el-message.css'
```

View File

@ -0,0 +1,41 @@
---
title: 不使用vue-router实现简单路由跳转
createTime: 2022/05/29 23:40:45
tags:
- Vue
categories:
- 随记
---
参考[simple-routing-from-scratch](https://vuejs.org/guide/scaling-up/routing.html#simple-routing-from-scratch)
官方给的是 vue2+js 的写法,用 vue3+ts 简单改一下:
```vue
<script setup lang="ts">
import { computed, reactive } from 'vue'
import Gadget from './views/Gadget.vue'
import HelloWorld from './views/HelloWorld.vue'
const data: any = reactive({
currentPath: window.location.pathname,
routes: {
'/': HelloWorld,
'/Gadget': Gadget,
},
})
window.addEventListener('hashchange', () => {
data.currentPath = window.location.hash
})
const currentView = computed(() => {
return data.routes[data.currentPath.slice(1) || '/'] || HelloWorld
})
</script>
<template>
<a href="./">Home</a> | <a href="#/Gadget">Gadget</a> |
<component :is="currentView" />
</template>
```

View File

@ -0,0 +1,20 @@
---
title: vite构建的vue3+ts改build路径
createTime: 2022/05/30 12:32:21
tags:
- Vue
categories:
- 随记
---
参考[build-outdir](https://vitejs.dev/config/#build-outdir)
`vite.config.ts`中修改配置:
```typescript
export default defineConfig({
build: {
outDir: 'docs'
}
})
```

View File

@ -0,0 +1,15 @@
---
title: npm换源
createTime: 2024/08/09 17:36:05
tags:
- npm
categories:
- 随记
---
```bash
# 查看当前源
npm config get registry
# 换淘宝源
npm config set registry=https://registry.npmmirror.com
```

View File

@ -0,0 +1,43 @@
---
title: 21.08.20前累积更新日志
createTime: 2026/04/02 20:26:36
---
## 21.06.19
1. 修复非管理员无法进行弹幕推送的问题
## 21.05.13
1. 新增弹幕功能添加基于Spring Boot的弹幕测试接口
## 21.05.11
1. 移除无用的工具类
2. 新增禁言管理、禁言时长缓存
3. 修复缓存Buffer找不到缓存文件时缓存失效的问题
4. @Function注解新增visible、needAdmin、needBotAdmin属性现在只有visible=true(default)的功能才会被放入功能列表
5. 新增权限管理可设置是否需要管理员操作、bot是否需要管理员权限
6. 修改function包下父类及接口类类名使之更符合实际功能
7. 新增BaseProperties -- botAlias属性
## 21.05.08
1. 建立仓库 [JX3Mirai](https://github.com/yuany3721/JX3Mirai/) 并发布demo v0.1 Pre Release
2. 建立缓存buffer包和@Buf注解提取Buffer父类
3. 完善JavaDoc
## 21.05.07
1. 新增疯狂的复读机功能
2. 新增群聊功能说明
3. 新增群聊功能开关
4. 修复无法识别不同图片区别的bug
5. 修复无法复读含有多图片消息的bug
6. 新增群聊消息缓存功能
7. 修复复读机不同群聊消息会相互混淆的bug
8. 复读机现在可以复读富文本消息了(如图片、引用、@等
9. 新增群临时会话、陌生人消息回复
## 21.05.06
1. 修改Listener注册方式

View File

@ -0,0 +1,32 @@
---
title: Bot更新日志
createTime: 2026/04/02 20:26:36
---
## 22.11.04
1. 由于服务器到期Bot 服务无限期暂停
## 21.09.15
1. 更新 mirai-core-jvm 至 2.7.1-dev-1修复 bot 无法发送群聊图片的问题 参考[mirai#1536](https://github.com/mamoe/mirai/issues/1536)
## 21.09.07
重新上线 bot
1. 修复“功能管理”和“禁言管理”在某些时候可能产生冲突的问题
2. 修复 bot 发送的消息不进入消息缓存队列的问题
3. 新增好友消息处理器
4. 新增涩图推送功能 关键词:涩图、无内鬼 彩蛋:涩图三连
## 21.08.27
1. 迁移开发日志
2. bot 不再能够禁言自己
3. bot 不再能够禁言群主或管理员
4. 禁言时间超过 43199 分钟后自动设置为 43199 分钟
---
- 停止弹幕系统服务,暂停 Bot 服务,预计恢复时间九月中旬

View File

@ -0,0 +1,17 @@
---
title: 更新日志
permalink: /更新日志/
createTime: 2026/04/02 20:26:36
---
**Home**
> Update Log of &nbsp;[yuany3721.top](http://yuany3721.top)
**站点 更新日志**
> See [Web](Web/)
**QQ Bot 更新日志**
> See [Bot](Bot/)

View File

@ -0,0 +1,200 @@
---
title: 21.08.16前累积更新日志
createTime: 2026/04/02 20:26:36
---
## 21.8.15
1. 修复首页功能导航错误和错误开启已关闭功能的问题
## 21.8.15
1. 加入**[certbot](https://github.com/certbot/certbot)**以提供更好的 https 服务
2. 优化主页代码结构
## 21.8.14(2)
1. 上线魔改板 filebrowser by yuany3721(Fork from **[filebrowser](https://github.com/filebrowser/filebrowser)**) TODO: 解决安卓浏览器不支持批量上传的问题
2. 更新 nginx 代理规则,优化不必要的请求转发
## 21.8.14
1. 将 swapfile 由 1G 增加到 4G
2. 重新开放管理信息系统、作业管理系统
## 21.7.24
1. 重新开放标注协同平台,开放对象改变为所有非游客
2. 新增 swapfile 内存交换区
## 21.5.28
1. 暂时关闭了标注协同平台
## 21.5.27
1. 由于 API 调用及版权问题,暂时下架了社交网络话题-情感分析系统
2. 由于服务器内存问题,暂时关闭了管理信息系统、作业管理系统
3. 修复无登录状态时用户留言无效的 bug
4. 现在积分变更记录至多显示 50 条
## 21.4.29
1. 修复社交平台网络-情感分析系统(beta)爬虫功能不兼容 Linux 的 bug
2. 优化社交平台网络-情感分析系统(beta)的数据爬取过程及后台状态逻辑
## 21.4.25
1. 一个基于 LDA 的社交平台话题-情感分析系统(beta)发布
2. 修复作业管理系统(beta)无法访问的 bug
## 20.10.25
1. 作业管理系统(beta)发布 By:董怡婷 刘艺瀛 阳灵鑫 李承霖
## 20.10.19
1. 更新网站 ssl 证书
## 20.5.27
1. 优化标注评论显示
## 20.5.25
1. 新增一致性检验需要文件生成、下载
2. 新增包含无情感评论的标记文件生成、下载
## 20.5.19
1. 新增已标记文件生成、下载
## 20.4.15
1. 新增标记缓存,以便同步各标记进度且不重复推送造成冲突
## 20.4.12
1. 更新已标记内容显示方式,避免标记量过大时页面渲染导致大量资源消耗
## 20.4.9
1. 更新标记查找为查找内容或标记状态
2. 更新标记修改、删除权限为任意已标记者
## 20.4.8
1. 优化标记选择方式
## 20.4.7
1. 上线微博评论情感细分类标注协同平台
## 20.4.5
1. 修复了某些情况下可以短时间内重复多次下载文件,会多次消耗积分且只弹出一次下载界面的问题
## 20.3.11
1. 批量添加用户
2. 更改登录注册显示效果
## 20.2.29
1. 新增登录控制 基本功能:登录、注册、个人中心、个人资料修改、游客登录 文件下载:现在所有的文件资源将需要在登录后下载,每次下载将消耗 1 积分和 1 每日下载次数 积分:注册/默认账号 将自动获得 40 积分,每日登录将获得 2 积分(如果您的积分用完了,可以尝试使用游客登录或者次日再来) 每日下载次数:默认账号每日下载次数为 20所有的游客每日共用下载次数 10 且不消耗积分
2. 新增登录控制下的留言,保留原留言方式 原留言方式:无需登录即可留言,但所有人均有权限看到您的留言 新留言方式:需登录方可留言,但只有管理员有权限看到您的留言
## 20.2.26
1. 新增小玩意入口,将原书名、姓名生成器移入小玩意目录内
---
## 项目部分重构,站点更新为 v2 版本20.2.26
1. 在不改变逻辑结构条件下,改变文件目录结构,改变绝大部分路由为懒加载
2. 删除并修改大量来自**[vue-element-responsive](https://github.com/caochangkui/vue-element-responsive-demo)**的代码,修改部分功能实现,使其更符合本站需要
---
## 20.2.25
1. 恢复默认页面鼠标样式
2. 修改首页高亮为主题颜色,修改首页导航字体样式
## 20.1.20
1. 为迎接新年,改版页面鼠标样式
## 19.12.30
1. 物联网静态网页部分显示效果更新
2. 加入未完成的根据日期改变的鼠标样式
3. 为迎接元旦到站长下一次更新前页面鼠标样式变为“2020”
## 19.12.26
1. 物联网静态网页(完整版)正式发布 鸣谢:**[中国物联网](http://www.iotcn.org.cn/)**、**[云计算世界](http://www.chinacloud.cn/)**该网页图源均为网络,如有侵权烦请联系删除
## 19.12.25
1. 新增不那么靠谱的悦读频道静态页面子域名
## 19.12.24(2)
1. 新增一个奇怪的姓名生成器
## 19.12.24
1. 新增未完成的物联网简介静态页面子域名
2. 添加可检索文献 8 篇(感谢 小婷婷 ♥ 倾情相助)
3. 修复信息检索有时可检索文献不显示的 bug
## 19.12.8
1. 修复信息检索\_作者检索时会将作者姓名作为检索式处理导致无法找到对应文章的错误
## 19.12.7(2)
1. 修复连续进入同一个页面后台会报错的问题
## 19.12.7
1. 新增一个奇怪的书名生成器
2. 首页提示信息现在可以直接点击前往了
## 19.12.6
1. 修复处于文件资源根目录下文件会显示为目录而不是可下载文件的错误
## 19.12.3
1. 更新可检索文章列表为自动获取,更改了文章列表的位置
2. 添加可检索文献 4 篇(这次多了点)
3. 增加更新日志内日期的年份显示
## 19.11.29
1. 优化检索时标题识别方案,现在的标题识别更加丝滑(?)
2. 添加可检索文献两篇(就两篇也好意思说?)
## 19.11.27
1. 修复了火锅店进货单不显示且无法选择食材列表的问题
2. 修复了 nginx 默认语言配置导致的留言一定会失败的问题
## 19.11.26(2)
1. 修复了某些浏览器查看文章会显示乱码的问题
2. 修复了不存在待处理文件时点击“刷新顺排档”会出现文件系统错乱的问题
## 19.11.26
1. 新增不完善的信息检索系统,存在大量待修改 bug
## 19.11.18
1. 优化了数据流程图、业务流程图过大导致的加载过慢问题
2. 修复了文件下载次数不随下载次数增加而增加的 bug
3. 修复了火锅店点餐失败的 bug如果仍然存在请刷新页面重试
4. 修复了文件下载次数始终不变的 bug

View File

@ -0,0 +1,81 @@
---
title: 22.05.16前累积更新日志
createTime: 2026/04/02 20:26:36
---
## 22.05.15
1. 重构[中文文献全文检索系统](http://ir.yuany3721.top)
- 使用Openjdk-11重构后端
- 使用Vue3、Element-Plus、Vite重构前端
- 迁移information_retrieval数据库至x4_640
2. 由于服务器资源等问题,暂时关闭了中文文献全文检索系统的新文献上传和处理功能
## 22.05.12
1. 重构[火锅店管理信息系统](http://glxxxt.yuany3721.top)
- 使用Openjdk-11重构后端
- 使用Vue3、Element-Plus、Vite重构前端
- 迁移glxxxt数据库至x4_640
2. 由于新的certbot使用snap管理而导致一系列问题暂时停止站内所有https访问
## 22.04.25
1. 修复mdblog中代码块显示异常问题修了但是没完全修
2. 修复更新文件后旧文件缓存仍然存在的问题
## 22.04.18
1. 停用WordPress服务原[https://wp.yuany3721.top](https://wp.yuany3721.top)
2. 新增MDBlog —— 一个基于 Flask 和 markdown 文档的轻量级博客([https://blog.yuany3721.top](https://blog.yuany3721.top)
3. 迁移原WordPress服务至MDBlog
## 21.10.15
1. 由于后台项目重构所有包括管理信息系统、用户管理、文件下载、信息检索、标注协同平台五个系统在内的所有服务将在CST 2021年10月19日DigiCert证书到期后不稳定或暂不提供服务恢复时间暂定。
## 21.10.14
1. 新增web notepad [http://notepad.yuany3721.top](http://notepad.yuany3721.top)
## 21.09.28
1. 新增震惊标题生成器
2. 新增恶俗古风诗句生成器
感谢[guofei9987](https://github.com/guofei9987)
## 21.09.11
1. 重新制作了站点logo ![file](https://wp.yuany3721.top/wp-content/uploads/2021/09/614315ae979db.png)
2. 更新首页及WordPress站点ico为新的logo
## 21.09.10
1. 修复分类目录中没有“未分类”的问题
2. 自动更新WordPress至5.8.1
3. 移除WordPress主页、文章页侧边栏中的搜索工具
## 21.08.31
1. 新增WordPress Category分类目录 [分类目录链接](https://wp.yuany3721.top/category)
2. 更新首页向WordPress的链接方式
3. 迁移部分CSDN文章至本站
## 21.08.27
1. 合并小玩意中姓名生成器和书名生成器
2. 新增彩虹屁生成器
TODO: 迁移element-ui的notification至element-plus
## 21.08.24
1. 搭建WordPress 感谢优秀的[WordPress](https://github.com/WordPress/WordPress)框架和[Kratos](https://github.com/Vtrois/Kratos)提供的主题
2. 在首页中新增WordPress站点入口 TODO: 迁移element-ui至element-plus将Font Icon向SVG Icon迁移参见[官方文档](https://element-plus.gitee.io/#/zh-CN/component/icon)
3. 去除首页入口提示,只保留功能列表
4. 将首页中冗长的更新日志迁移至WordPress
## 21.08.23
1. 上线[七七云打卡平台](https://auto.biqiqi.com.cn)备用镜像

View File

@ -0,0 +1,34 @@
---
title: 23.05.01前累积更新日志
createTime: 2026/04/02 20:26:36
---
## 22.11.04
1. 迁移域名至yuany3721.site暂停火锅店管理信息系统、信息检索系统、作业管理系统待迁移到新服务器
## 22.10.06
1. 简化tag分类标注
## 22.07.31
1. 简化tag标注
## 22.05.31
1. 首页加入必应首页图片背景,修改相应样式
## 22.05.30
1. 使用 vite + vue3 + ts + element-plus 重构[主页](https://yuany3721.top),整理各项目
## 22.05.17
1. 迁移MDBlog至[Vuepress](http://blog.yuany3721.top),更新日志同步迁移到[Vuepress](http://blog.yuany3721.top/updatelog)
主题魔改自优秀的[vuepress-theme-reco](https://vuepress-theme-reco.recoluan.com)
~~之前没发现Vuepress和markdown-it-katex跑去写了个基于flask的markdown文档管理页面真像个大冤种呢~~
## 22.05.16
1. 使用[docsify](https://github.com/docsifyjs/docsify/)迁移更新日志到[新的更新日志](http://updatelog.yuany3721.top)

View File

@ -0,0 +1,50 @@
---
title: Web更新日志
createTime: 2026/04/02 20:26:36
---
## 25.03.22
1. 迁移 blog 到[vuepress-theme-plume](https://theme-plume.vuejs.press/)
## 24.12.17
1. 停止文件中转站服务
## 24.08.11
1. 部署基于[FileCodeBox](https://github.com/vastsa/FileCodeBox)的[文件中转站](https://filebox.yuany3721.site)
2. 停止了周计划页面维护与更新
3. 更新主页内容和链接,更新已暂停服务的说明
## 23.07.22
1. 部署基于[homepage](https://github.com/benphelps/homepage)的[导航页](https://home.yuany3721.site)
2. 部署[focalboard](https://github.com/benphelps/homepage)于[board](https://board.yuany3721.site)
3. 优化主页内容展示逻辑,修复 Card 中`<a>`标签的点击事件冒泡问题
4. 更新主页内容和链接更新了已暂停服务的说明适配了新增的周计划、导航页、board
## 23.06.30
1. 新增[周计划](https://plan.yuany3721.site)页面
## 23.06.14
1. 将主页从 GitPage 迁移至阿里云
2. 更新主页的必应每日背景图片来源为[官方来源](https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1),使用 Flask 绕过 CORS 限制
## 23.06.13
1. 新增[光功率换算工具](https://yuany3721.site/tools#光功率单位转换工具)
2. 修复进制转换工具输入内容含十六进制字符时的 bug
## 23.05.08
1. 新增[进制转换小工具](https://yuany3721.site/tools#进制转换工具)
2. 恢复 ssl 访问
3. 恢复[wlw](https://wlw.yuany3721.site)、[ydpd](https://ydpd.yuany3721.site)访问
## 23.05.02
1. 新增车牌归属地查询小工具
2. 修改部分页面样式,删除冗余代码

View File

@ -0,0 +1,4 @@
---
createTime: 2026/04/02 21:53:02
title: 笔记
---

View File

@ -0,0 +1,81 @@
---
title: 计算机的开机过程
createTime: 2013/10/31
tags:
categories:
- 杂谈
---
计算机的整个启动过程分成四个阶段。
一、第一阶段BIOS
上个世纪 70 年代初“只读内存”read-only memory缩写为 ROM发明开机程序被写入 ROM 芯片,计算机通电后,第一件事就是读取它。
这块芯片里的程序叫做”基本输出输入系统”Basic Input/Output System简称为 BIOS。
BIOS 中主要存放的程序包括自诊断程序、CMOS 设置程序、系统自动装载程序和主要 I/O 驱动程序和中断。
BIOS 程序首先检查计算机硬件能否满足运行的基本条件这叫做”硬件自检”Power-On Self-Test缩写为 POST。
如果硬件出现问题,主板会发出不同含义的蜂鸣,启动中止。如果没有问题,屏幕就会显示出 CPU、内存、硬盘等信息。
硬件自检完成后BIOS 把控制权转交给下一阶段的启动程序。
这时BIOS 需要知道“下一阶段的启动程序”具体存放在哪一个设备。也就是说BIOS 需要有一个外部储存设备的排序排在前面的设备就是优先转交控制权的设备。这种排序叫做“启动顺序”Boot Sequence
二、第二阶段:主引导记录
BIOS 按照“启动顺序”,把控制权转交给排在第一位的储存设备。这时,计算机读取该设备的第一个扇区,也就是读取最前面的 512 个字节。如果这 512 个字节的最后两个字节是 0x55 和 0xAA表明这个设备可以用于启动如果不是表明设备不能用于启动控制权于是被转交给”启动顺序”中的下一个设备。
这最前面的 512 个字节就叫做“主引导记录”Master boot record缩写为 MBR
主引导记录由三个部分组成调用操作系统的机器码、分区表Partition table和主引导记录签名0x55 和 0xAA。它的主要作用是告诉计算机到硬盘的哪一个位置去找操作系统。
其中,分区表的作用是将硬盘分成若干个区。考虑到每个区可以安装不同的操作系统,“主引导记录”必须知道将控制权转交给哪个区。
分区表的长度只有 64 个字节,里面又分成四项,每项 16 个字节。所以,一个硬盘最多只能分四个一级分区,又叫做“主分区”。
每个主分区的 16 个字节,由 6 个部分组成:
1 第 1 个字节:如果为 0x80就表示该主分区是激活分区控制权要转交给这个分区。四个主分区里面只能有一个是激活的。
2 第 2-4 个字节:主分区第一个扇区的物理位置(柱面、磁头、扇区号等等)。
3 第 5 个字节:主分区类型。
4 第 6-8 个字节:主分区最后一个扇区的物理位置。
5 第 9-12 字节:该主分区第一个扇区的逻辑地址。
6 第 13-16 字节:主分区的扇区总数。决定了这个主分区的长度。
三、第三阶段:硬盘启动
这时,计算机的控制权就要转交给硬盘了,这里又分成三种情况。
情况 A卷引导记录
计算机会读取激活分区的第一个扇区叫做“卷引导记录”Volume boot recordVBR。“卷引导记录”的主要作用是告诉计算机操作系统在这个分区里的位置。然后计算机就会加载操作系统了。
情况 B扩展分区和逻辑分区
随着硬盘越来越大四个主分区已经不够了需要更多的分区。但是分区表只有四项因此规定有且仅有一个区可以被定义成”扩展分区”Extended partition
所谓”扩展分区”就是指这个区里面又分成多个区。这种分区里面的分区就叫做”逻辑分区”logical partition
计算机先读取扩展分区的第一个扇区叫做“扩展引导记录”Extended boot record缩写为 EBR。它里面也包含一张 64 字节的分区表,但是最多只有两项(也就是两个逻辑分区)。
计算机接着读取第二个逻辑分区的第一个扇区,再从里面的分区表中找到第三个逻辑分区的位置,以此类推,直到某个逻辑分区的分区表只包含它自身为止(即只有一个分区项)。因此,扩展分区可以包含无数个逻辑分区。
因其繁复性,很少通过这种方式启动操作系统。如果操作系统确实安装在扩展分区,一般采用下一种方式启动。
情况 C启动管理器
在这种情况下不再把控制权转交给某一个分区而是运行事先安装的“启动管理器”boot loader由用户选择启动哪一个操作系统。
四、第四阶段:操作系统
控制权转交给操作系统后,操作系统的内核首先被载入内存,接着是一系列的模块,比如窗口程序和网络程序等,最后跳出登陆界面。
至此,全部启动过程完成。

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