《SQLite3》面向对象包装 SQLite3 C/C++ 基础接口(02)
线程安全问题
SQLite3 在编译的时候可以通过添加定义来控制整个库的线程安全问题。
当 SQLITE_THREADSAFE 这个宏为 0 时,整个库是线程不安全的。
当 SQLITE_THREADSAFE 这个宏为 1 时,整个库是线程安全的。
当 SQLITE_THREADSAFE 这个宏为 2 时,整个库是线程安全的,但是同一个 sqlite3* db 不能被多个线程同时使用。
当编译的时候 SQLITE_THREADSAFE 为 1 或者 2 时,可以通过 sqlite3_config() 这个接口来更改线程安全模式:
SQLITE_CONFIG_SINGLETHREAD单线程SQLITE_CONFIG_MULTITHREAD多线程SQLITE_CONFIG_SERIALIZED串行化
面向对象类
1 | #include <functional> |
我设置了两个成员变量,一个是数据库连接,另一个是打开的数据库名称。1
2std::string db_name_;
sqlite3* db_{nullptr};
数据库的开启
首先是类的构造函数,主要是打开数据库连接,并在出错时抛出异常信息。1
2
3
4
5
6SQLite3::SQLite3(const std::string_view& db_name) : db_name_(db_name) {
auto errcode = sqlite3_open(db_name.data(), &db_);
if (errcode != SQLITE_OK) {
// 抛出或处理异常信息
}
}
数据库的关闭
然后是析构和关闭数据库连接。
析构函数因为不能抛出异常,所以我使用了 sqlite3_close_v2 来关闭连接。
主动 close 则是使用 sqlite3_close 接口,并返回错误代码。1
2
3
4
5
6
7
8
9
10
11
12
13
14SQLite3::~SQLite3() {
if (db_) {
sqlite3_close_v2(db_);
db_ = nullptr;
}
}
int SQLite3::close() {
auto errcode = sqlite3_close(db_);
if (errcode == SQLITE_OK) {
db_ = nullptr;
}
return errcode;
}
执行 SQL 语句
无回调函数
无回调函数的操作,只需要执行 SQL 语句,并抛出或者处理执行失败的情况即可。1
2
3
4
5
6
7
8
9
10
11void SQLite3::exec(const std::string_view& sql) {
char* errstr = nullptr;
int errcode = sqlite3_exec(db_, sql.data(), nullptr, nullptr, &errstr);
if (errcode != SQLITE_OK) {
std::string msg = errstr ? errstr : "Unknown error";
sqlite3_free(errstr);
throw std::runtime_error(
std::format("Failed to execute SQL: {}\nError SQL: {}", msg, sql));
}
}
有回调函数
当执行一些带有结果的 SQL 语句时,就需要回调函数去处理结果。
我定义了两个类型用来封装 sqlite3_exec 中的回调函数。
ExecCallback 对象的返回值为 bool 类型,用来指示回调函数是否成功执行。
并且 ExecCallback 对象拥有一个参数 TableRow,这是一个哈希表,存储该行的每一个列数据的 name 和 value 的键值对。1
2using TableRow = std::unordered_map<std::string, std::string>;
using ExecCallback = std::function<bool(TableRow)>;
我通过 void* context 传递 ExecCallback 对象。
当回调函数触发时,填充 TableRow row 对象的数据,并以此为参数调用 ExecCallback 对象。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23void SQLite3::exec(const std::string_view& sql, ExecCallback callback) {
auto c_callback = [](void* context, int col_size, char** col_values,
char** col_names) -> int {
auto* cb = static_cast<ExecCallback*>(context);
TableRow row;
for (int i = 0; i < col_size; i++) {
std::string col_name = col_names[i];
std::string value = col_values[i] ? col_values[i] : "";
row[col_name] = value;
}
bool success = (*cb)(row);
return success ? 0 : 1;
};
char* errstr = nullptr;
int errcode = sqlite3_exec(db_, sql.data(), c_callback, &callback, &errstr);
if (errcode != SQLITE_OK) {
std::string msg = errstr ? errstr : "Unknown error";
sqlite3_free(errstr);
throw std::runtime_error(std::format(
"Failed to execute SQL with callback: {}\nError SQL: {}", msg, sql));
}
}
测试一下这个类
1 | int main() { |
运行上述 main 函数后,获得输出如下:1
2
3User ID: 1, Name: Alice
User ID: 2, Name: Bob
User ID: 3, Name: Charlie
再次运行该代码,输出如下:1
2Failed to execute SQL: UNIQUE constraint failed: users.id
Error SQL: insert into users (id, name) values (1, 'Alice');
测试完毕,这样一个初步的面向对象封装就完成了。
《SQLite3》SQLite3 C/C++ 基础接口(01)
介绍
最基本的使用 sqlite3 的 c api 还是挺简单的。只需要记住三个接口即可。
打开数据库:
sqlite3_open()关闭数据库:
sqlite3_close()执行 SQL 语句:
sqlite3_exec()
开启数据库
先来看看如何开启数据库,我们需要提供两个参数,数据库名称和一个 sqlite3 指针的指针。1
2
3
4int sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
具体的使用基本如下:1
2
3char* db_name = "test.db";
sqlite3* db;
sqlite3_open(db_name, &db);
SQLite3 还提供了可以更加精细的控制打开数据库方式的接口:sqlite3_open_v2()1
2
3
4
5
6int sqlite3_open_v2(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb, /* OUT: SQLite db handle */
int flags, /* Flags */
const char *zVfs /* Name of VFS module to use */
);
可以看到多了两个参数,可以控制数据库只读或其他更精细的操作。sqlite3_open() 可以看作是下述特定参数 sqlite3_open_v2()。1
2
3char* db_name = "test.db";
sqlite3* db;
sqlite3_open_v2(db_name, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
具体的 sqlite3_open_v2() 使用可以参考官方文档 Opening A New Database Connection.
关闭数据库
关闭数据库只需要把 sqlite3* db 作为参数传入即可。使用十分简单。
就像 open 接口有多个版本一样,close 接口也有多个版本。1
2int sqlite3_close(sqlite3*);
int sqlite3_close_v2(sqlite3*);
主要区别是,当 db 还有某些未完成的任务时,两个接口会有不同的行为。
sqlite3_close 会返回 SQLITE_BUSY。
sqlite3_close_v2 会返回 SQLITE_OK。但不会立即释放数据库连接,而是将数据库连接标记为不可用的“僵尸”状态,并安排在所有预处理语句完成、所有 BLOB 句柄关闭以及所有备份操作结束后自动释放数据库连接。
执行 SQL 语句
1 | int sqlite3_exec( |
db 是打开的数据库连接。
sql 是要执行的 SQL 语句。
callback 是执行完 SQL 语句后进行的回调函数。(可选参数,不需要可传递空指针)
data 是传给 callback 的第一个参数,可用于传递上下文。(可选参数,不需要可传递空指针)
errmsg 会返回相应的错误信息,如果无错误则被设为空指针。(可选参数,不需要可传递空指针)
回调函数
1 | int callback(void* context, int col_size, char** col_values, char** col_names); |
只要理解了这个回调函数会 对结果的每一行数据执行一次,我们就可以轻松的理解这个回调的后面三个和列相关的参数。
context:从 sqlite3_exec() 传递过来的用户数据col_size:结果行的列数col_values:列值的字符串数组col_names:列名的字符串数组
返回值为 0 时,继续查询。
返回值为 1 时,终止查询。
白名单模式的 gitignore 配置
虽然已经用了多年的 git, 但是至今都没怎么好好的总结一下 ignore 规则。今天心血来潮,重新仔细的总结一下 gitignore 到底怎么好好的去写,并记录一下 gitignore 的白名单写法。
基础规则
首先是 gitignore 的基础规则。基础规则的总结,我参考了这篇文章 .gitignore File – How to Ignore Files and Folders in Git. 不过参考文章中有些操作在我所使用的 Archlinux 中无法复现, 所以下面的总结以我自己的实际操作为基础。
如何在 Git 中忽略一个文件或文件夹
如何忽略一个文件或目录
1 | /text.txt # 忽略根目录下 text.txt 文件 |
如何不忽略一个文件或目录
加入我们忽略了所有 md 文件, 但唯独不忽略 README.md 的情况, 如下所示.1
2*.md # 忽略所有名字结尾是 .md 的文件和目录
!README.md # 不忽略所有名字是 README.md 的文件和目录
无法排除已经被忽略的目录内的一个文件
1 | test/ # 忽略所有名字带有 test 的目录 |
如何忽略以前提交的文件
假如你不小心把 .build 文件提交了, 现在想去除这个文件. 过程如下所示.1
2
3
4
5
6
7
8
9
10
11
# 给 .gitignore 添加 .build 文件
echo ".build" >> .gitignore
# 从 git 版本库中去除该文件
git rm --cached .build
# 暂存新的 .gitignore 并提交
git add .gitignore
git commit -m " 更新了 .gitignore 文件 "
白名单模式
一般来说 gitignore 是使用黑名单模式,也就是写在 ignore 中的项目会被忽略,但是有些时候使用黑名单模式会有一些疏漏,当项目逐渐庞大起来,难免会有一些遗漏,将一些临时的文件和不希望添加入 git 管理的文件加入 git 中。这个时候白名单模式的 gitignore 能够实现更加精细的管理。
假设我们有以下结构的 C++ 项目需要管理:1
2
3
4
5
6
7your-project-dir
├── .gitignore # gitignore 文件
├── build/ # 构建项目的临时目录
├── docs/ # 放置各种文档
├── include/ # 放置 .h 头文件
├── README.md # 自述文档
└── src/ # 放置 .cpp 代码文件
首先忽略全部文件,并取消忽略目录
白名单模式的第一步。这里取消忽略目录,是因为被忽略目录下的文件是必定被忽略的,为了能够指定不忽略的文件,需要取消忽略目录。1
2*
!*/
忽略不想要的目录 (可选)
因为 build 目录完全是一个临时目录,我不想提交里面的任何文件,所以可以直接忽略掉。如果这个目录里有某些特定的文件需要提交,则不应该忽略这个目录。
之所以这是一个可选的操作,是因为在上一步忽略了所有文件之后,所有的目录内都没有需要提交的文件,在 git 中这样的“空目录”不会被提交。1
/build/
取消忽略特定的文件
有些文件我们希望必须提交的,我们可以直接取消忽略这些文件。1
2!.gitignore
!README.md
这样之后,任何目录下的 .gitignore 和 README.md 文件都会被提交上去。
取消忽略特定目录下的全部文件
我希望提交 docs 目录下的所有文件,包括其子目录下的所有文件。通过下面这种写法,可以取消忽略 docs 目录下的所有文件,并递归的忽略其子目录下的所有文件。1
!/docs/**/*
取消忽略特定目录下的特定文件
有的目录我只希望提交特定类型的文件,例如 src 目录下的 .cpp 代码文件和 include 目录下的 .h 头文件。
下面这种写法取消忽略了对应目录下所有特定后缀的文件,并递归的忽略其子目录下所有特定后缀的文件。1
2!/include/be/**/*.h
!/src/be/**/*.cpp
总结
最后的白名单 gitignore 文件看上去是这样的:1
2
3
4
5
6
7
8
9
10
11*
!*/
/build/
!.gitignore
!README.md
!/docs/**/*
!/include/be/**/*.h
!/src/be/**/*.cpp
在比较复杂的项目中,或者需要精细控制提交的文件时,白名单模式的 ignore 文件是真的很好用。
Mihomo 纯内核运行
因为在 Archlinux 上使用 Clash Verge Rev 经常会出现一些奇怪的问题,比如说 service 无法运行,界面卡顿加载不出来,甚至会直接卡死。所以很早之前我就有了直接跑纯内核的念头。
故现在我终于开始尝试直接跑纯 Mihomo 内核,目前是已经完成了所有的配置,普通模式和 Tun 模式都可以正常使用。现将过程记录如下。
由于我是在 Archlinux 上进行的安装,我可以确保在 Archlinux 上以下操作全部经过检验。
安装 mihomo 核心及其依赖
实际上包管理器会自动处理依赖,所以不用担心。1
yay -S mihomo
安装 metacubexd 界面
为了能够在 web 端方便的临时调整配置,以及可视化连接及流量,我推荐安装 metacubexd 这个界面。
如果你配置了 archlinuxcn 源,可以直接 pacman 安装预编译版本。1
sudo pacman -S metacubexd-bin
也可以在 AUR 中安装,metacubexd-bin 是预编译版本,metacubexd 是源码需要本机上编译。我比较推荐预编译版本。1
yay -S metacubexd-bin
启动守护进程
AUR 中提供的 mihomo 软件包里面自带了 systemd 守护进程 mihomo.service,我们需要手动 enable 让 mihomo 内核可以开机自启。1
sudo systemctl enable mihomo.service
然后启动 mihomo 内核进行下一步工作。1
sudo systemctl start mihomo.service
配置文件
通过查看守护进程文件 /etc/systemd/system/multi-user.target.wants/mihomo.service 可以看到我的 mihomo 的工作目录为 /etc/mihomo, mihomo 内核的配置文件在 /etc/mihomo/config.yaml 中,我们需要修改这个文件来配置我们的 mihomo 内核。
config.yaml 这个文件就是最主要的配置文件,只不过我们需要修改一些内容。来适合我的使用习惯。
首先把 config.yaml 中的所有内容清空,然后把机场给出的配置文件整个的复制过来。
接下来就是修改修改了。
修改端口
因为 Clash Verge Rev 的默认 mixed-port 是 7897, 我的很多软件的代理都设置为了这个端口,所以我也依旧修改 mixed-port 为 7897.
并且我不喜欢开启局域网访问,所以我将 allow-lan 修改为 false.
现在,我的 config.yaml 大概是这个样子。1
2
3
4
5
6
7
8
9
10
11
12
13
14mixed-port: 7897
port: 7890
socks-port: 7891
allow-lan: false
mode: Rule
log-level: info
external-controller: 127.0.0.1:9090
proxies:
# ...
proxy-groups:
# ...
rules:
# ...
我们需要重启 mihomo 内核,让配置生效。1
sudo systemctl restart mihomo.service
这个时候,mihomo 就已经可以正常的使用了。
但是 Tun 模式目前还用不了,接下来我们继续设置。
配置 metacubexd 界面
1 | # 前端控制器界面 (archlinuxcn 源中的 metacubexd) |
只需要在 config.yaml 中加上这一行就可以,archlinuxcn 源中的 metacubexd-bin 的目录是在 /usr/share/metacubexd 中。AUR 中的我没有尝试过,大家下载下来之后可以使用 pacman -Ql metacubexd-bin 查看一下具体的路径。
然后我们需要重启 mihomo 内核,让配置生效。1
sudo systemctl restart mihomo.service
然然后我们就可以在浏览器中通过配置文件中 external-controller: 127.0.0.1:9090 的地址来访问 metacubexd 界面了。
记得加上 /ui 这个后缀,否则进不去 metacubexd 的界面。1
http://127.0.0.1:9090/ui
那么现在我们的配置就都完成的差不多了, config.yaml 大概是这个样子。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17mixed-port: 7897
port: 7890
socks-port: 7891
allow-lan: false
mode: Rule
log-level: info
external-controller: 127.0.0.1:9090
# 前端控制器界面 (archlinuxcn 源中的 metacubexd)
external-ui: /usr/share/metacubexd
proxies:
# ...
proxy-groups:
# ...
rules:
# ...
高级配置
DNS 配置
根据我的测试,不配置 dns 就无法使用 Tun 模式,所以我们这里直接给出我已经配置好的配置,大家可以直接复制粘贴到 config.yaml 中。
具体的选项起到什么作用其实还是很直接的,有想自己自定义的可以查看官方 Wiki 上的配置选项。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# DNS
dns:
enable: true
ipv6: true
listen: 0.0.0.0:53
enhanced-mode: fake-ip # redir-host
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- geosite:fakeip-filter
default-nameserver:
- system
nameserver:
- https://doh.pub/dns-query
- https://dns.alidns.com/dns-query
- https://dns.google/dns-query
- https://cloudflare-dns.com/dns-query
proxy-server-nameserver:
- https://doh.pub/dns-query
Tun 模式配置
Tun 模式的具体配置我没有在 config.yaml 中进行配置,而是直接使用的默认配置,在 web 界面上直接开启 Tun 模式即可使用。
其他配置
我还从 Wiki 上找了几个比较有用的配置1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22# web 界面的登录密码
# (因为我这里监听的 127.0.0.1 只有本机能够访问, 暂不设置)
# secret: ""
#【Mihomo 专属】TCP 连接并发,如果域名解析结果对应多个 IP,
# 并发所有 IP,选择握手最快的 IP 进行连接
tcp-concurrent: true
# 配置缓存 (代理中选择的节点和 fake-ip 缓存)
profile:
store-selected: true
store-fake-ip: true
#【Mihomo 专属】使用 geoip.dat 数据库(默认:false 使用 mmdb 数据库)
geodata-mode: true
geo-auto-update: true # 自动更新
geo-update-interval: 24 # 更新间隔 24 小时
geox-url: # 下载 geoip.dat 数据库的地址
geoip: "https://cdn.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo/geoip-all.dat"
geosite: "https://cdn.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo/geosite-all.dat"
mmdb: "https://cdn.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo/Country-all.mmdb"
asn: "https://cdn.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo/Country-ASN-all.mmdb"
最终配置
最后的配置大概长这个样子。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70mixed-port: 7897
port: 7890
socks-port: 7891
allow-lan: false
mode: Rule
log-level: info
external-controller: 127.0.0.1:9090
# 前端控制器界面 (archlinuxcn 源中的 metacubexd)
external-ui: /usr/share/metacubexd
# web 界面的登录密码
# (因为我这里监听的 127.0.0.1 只有本机能够访问, 暂不设置)
# secret: ""
#【Mihomo 专属】TCP 连接并发,如果域名解析结果对应多个 IP,
# 并发所有 IP,选择握手最快的 IP 进行连接
tcp-concurrent: true
# 配置缓存 (代理中选择的节点和 fake-ip 缓存)
profile:
store-selected: true
store-fake-ip: true
#【Mihomo 专属】使用 geoip.dat 数据库(默认:false 使用 mmdb 数据库)
geodata-mode: true
geo-auto-update: true # 自动更新
geo-update-interval: 24 # 更新间隔 24 小时
geox-url: # 下载 geoip.dat 数据库的地址
geoip: "https://cdn.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo/geoip-all.dat"
geosite: "https://cdn.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo/geosite-all.dat"
mmdb: "https://cdn.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo/Country-all.mmdb"
asn: "https://cdn.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo/Country-ASN-all.mmdb"
# DNS
dns:
enable: true
ipv6: true
listen: 0.0.0.0:53
enhanced-mode: fake-ip # redir-host
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- geosite:fakeip-filter
default-nameserver:
- system
nameserver:
- https://doh.pub/dns-query
- https://dns.alidns.com/dns-query
- https://dns.google/dns-query
- https://cloudflare-dns.com/dns-query
proxy-server-nameserver:
- https://doh.pub/dns-query
# nameserver-policy:
# "geosite:cn,private":
# - https://doh.pub/dns-query
# - https://dns.alidns.com/dns-query
# "geosite:ads":
# - rcode://success
# "geosite:!cn,!private,!ads":
# - https://dns.google/dns-query
# - https://cloudflare-dns.com/dns-query
proxies:
# ...
proxy-groups:
# ...
rules:
# ...
在 dns 配置中,可以配置 nameserver-policy 来实现不同的域名使用不同的 DNS 服务器。可以非常有效的解决 dns 泄漏问题,但是不知道为什么,我用起来网址解析的非常慢,所以我没有使用这个配置,而是注释掉了。
现在我的配置已经可以正常使用了,无论是走端口代理,还是直接 Tun 模式接管一切都没有任何问题了。
手写脚本实现一键更新订阅
首先把需要附加的配置写在 append.yaml 中。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64# append.yaml
mixed-port: 7897
port: 7890
socks-port: 7891
allow-lan: false
mode: Rule
log-level: info
external-controller: 127.0.0.1:9090
# 前端控制器界面 (archlinuxcn 源中的 metacubexd)
external-ui: /usr/share/metacubexd
# web 界面的登录密码
# (因为我这里监听的 127.0.0.1 只有本机能够访问, 暂不设置)
# secret: ""
#【Mihomo 专属】TCP 连接并发,如果域名解析结果对应多个 IP,
# 并发所有 IP,选择握手最快的 IP 进行连接
tcp-concurrent: true
# 配置缓存 (代理中选择的节点和 fake-ip 缓存)
profile:
store-selected: true
store-fake-ip: true
#【Mihomo 专属】使用 geoip.dat 数据库(默认:false 使用 mmdb 数据库)
geodata-mode: true
geo-auto-update: true # 自动更新
geo-update-interval: 24 # 更新间隔 24 小时
geox-url: # 下载 geoip.dat 数据库的地址
geoip: "https://cdn.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo/geoip-all.dat"
geosite: "https://cdn.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo/geosite-all.dat"
mmdb: "https://cdn.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo/Country-all.mmdb"
asn: "https://cdn.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo/Country-ASN-all.mmdb"
# DNS
dns:
enable: true
ipv6: true
listen: 0.0.0.0:53
enhanced-mode: fake-ip # redir-host
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- geosite:fakeip-filter
default-nameserver:
- system
nameserver:
- https://doh.pub/dns-query
- https://dns.alidns.com/dns-query
- https://dns.google/dns-query
- https://cloudflare-dns.com/dns-query
proxy-server-nameserver:
- https://doh.pub/dns-query
# nameserver-policy:
# "geosite:cn,private":
# - https://doh.pub/dns-query
# - https://dns.alidns.com/dns-query
# "geosite:ads":
# - rcode://success
# "geosite:!cn,!private,!ads":
# - https://dns.google/dns-query
# - https://cloudflare-dns.com/dns-query
因为我的订阅中已经有了一些配置,这些配置会和 append.yaml 中的配置冲突,所以通过 sed 进行删除处理。1
2
3
4
5
6
7
8
9
10
11
12
13
14#!/usr/bin/bash
# 获取机场配置,去除前 6 行,保存到 tmp.yaml
curl -L '< 你的订阅地址 >' | sed '1,6d' > tmp.yaml
# 附加 append.yaml 到 tmp.yaml
cat append.yaml >> tmp.yaml
# 原来配置的备份到 config.yaml.bak
cp config.yaml config.yaml.bak
# 用 tmp.yaml 替换 config.yaml
cat tmp.yaml > config.yaml
之后使用 sudo systemctl restart mihomo 重启一下 mihomo 服务,或者在 web 界面中重新读取一下配置即可完成更新。
其他
mmdb
- 第一次启动的时候 mihomo 会下载 mmdb,可能会因为网络问题下载失败,从而没法成功运行。可以先设置好 geox-url 的 cdn 地址,然后重启即可下载成功。
1 | geox-url: # 下载 geoip.dat 数据库的地址 |
ssh in Tun mode
- Tun 模式下 ssh 之类的软件都无法使用,因为连接的 ip 都会变成 198.18.0.1 这个地址。经过评论区中大佬的提醒,我找到了一个解决方法。在 dns 配置的
fake-ip-filter:这一项中,把想要 ssh 连接的域名和 ip 填上去就行。否则无论是通过域名进行连接还是直接通过 ip 连接,都会连接不上。
proxy-providers
- 经提醒,纯内核也支持配置订阅连接。经过一番折腾过后,我发现虽然支持订阅连接,但是 proxy-providers 似乎只导入其中的 proxies,但是对我来说 proxy-groups 和 rules 也是非常需要的,故暂不使用此功能。
external-ui
- 新版的 mihomo 对 web 界面的存放目录有了要求,可能需要将 metacubexd 的存放目录放到符合要求的位置。