diff --git a/public/404.html b/public/404.html new file mode 100644 index 0000000..bea7c8f --- /dev/null +++ b/public/404.html @@ -0,0 +1,130 @@ + + + + + +404 | Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+

Lost?

+

This page does not exist.

+
+ +
+ + + + +
+ + + diff --git a/public/about-2024/index.html b/public/about-2024/index.html new file mode 100644 index 0000000..3e88ac6 --- /dev/null +++ b/public/about-2024/index.html @@ -0,0 +1,221 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:2024年度总结

+ + + + + + +
+

前言 又是新的一年,时间流速感觉越来越快了。

+

大事记

+
    +
  • 六月份暑假将家里大翻新,包括水晶头,吊灯,门锁,水龙头等等;
  • +
  • 买了新柜子,房间更有序了;
  • +
  • 和朋友们聚餐;
  • +
  • 采用Mesh进行家庭组网;
  • +
  • 安装了一盏太阳能路灯,院子里更明亮了;
  • +
  • 和父母看电影;
  • +
  • 将博客迁移到新平台,用上亚马逊CDN;
  • +
  • 更换域名,不再续费 .ink;
  • +
  • 使用国家补贴更换电脑,换掉了故障百出的机械革命;
  • +
  • 办理校园网套餐并注销掉旧的电话卡;
  • +
  • 买了一台AX3000路由器并刷成openwrt,绕过校园网检测;
  • +
  • 开了azure虚拟机并研究;
  • +
  • 卖掉了chromebook;
  • +
  • 配置了Qemu虚拟机;
  • +
  • 给父母加装了流量包;
  • +
  • 更换了鼠标,并买了显示器和沙发椅;
  • +
  • 家里更换新热水器;
  • +
  • 修理亲戚家的网络问题;
  • +
  • 在学校和家里两处配备常用药箱;
  • +
  • 将所有设备更换为typec接口;
  • +
  • 整理并精简了RSS订阅源;
  • +
  • 重构了书签结构,增加用途分类;
  • +
  • 用上了Android 15,并使用多种开源软件;
  • +
  • 研究不同的root方案并完美隐藏环境;
  • +
  • 自制养生茶,咖啡和燕麦粥;
  • +
  • 养成跑步习惯;
  • +
  • 使用Deepl api进行翻译学习;
  • +
  • 看Netflix并研究浏览器环境检测;
  • +
  • 搭建Syncthing同步服务器实现三端同步;
  • +
  • 定时备份重要数据;
  • +
  • 学习英语纪录片,每天背单词;
  • +
+

成长与反思

+
    +
  • 谋定而后动,不要冲动消费;
  • +
  • 实践出真知,不要轻易下定论;
  • +
  • 适合自己的才是最好的;
  • +
  • 锻炼自身,早点睡觉,饮食规律是最好的养生;
  • +
+

新的一年的目标

+
    +
  • 在各大SRC平台挖点漏洞;
  • +
  • 封装一个完美的windows系统用于对外使用;
  • +
  • 研究并总结各大代理技术;
  • +
  • 重构家庭数据中心;
  • +
  • 学习一门新的语言并熟悉一种业务;
  • +
  • 控制体重并研究低成本健身;
  • +
+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-accurate-pronunciation/index.html b/public/about-accurate-pronunciation/index.html new file mode 100644 index 0000000..6aa5b35 --- /dev/null +++ b/public/about-accurate-pronunciation/index.html @@ -0,0 +1,270 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:常见发音错误术语集合

+ + + + + + +
+

前言 中文和英语发音习惯不同,容易引起误解。本文旨在帮助您准确发音常见的科技术语,欢迎随时补充。

+ +

常见发音错误指南:公司/产品名

+
    +
  • +

    Youtube: 正确念法是 "You-tube" [tju:b],而不是 "优吐毙",应该是 "优tiu啵"。

    +
  • +
  • +

    Skype: 应该念为 [ˈskaɪp],而不是 "死盖屁",应该是 "死盖破"。

    +
  • +
  • +

    Adobe: 正确的发音是 [əˈdəʊbi],不是 "阿斗伯",而是 "阿兜笔"。

    +
  • +
  • +

    C#: 应该念为 "C Sharp",即"C煞破"。

    +
  • +
  • +

    GNU: 正确的发音是 [(g)nuː], 即"哥怒"。

    +
  • +
  • +

    GUI: 应该念为 [ˈɡui],即"故意"。

    +
  • +
  • +

    JAVA: 正确的发音是 [ˈdʒɑːvə],而不是 "夹蛙",应该是 "扎蛙"。

    +
  • +
  • +

    AJAX: 应该念为 [ˈeɪdʒæks],而不是 "阿贾克斯",应该是 "诶(ei) 贾克斯"。

    +
  • +
  • +

    Ubuntu: 正确的发音是 [uˈbuntuː],而不是 "友邦兔",应该是 "巫不恩兔"。

    +
  • +
  • +

    Debian: 应该念为 [ˈdɛbiən],即"得(dei)变"。

    +
  • +
  • +

    Linux: 正确的发音有两种,[ˈlɪnəks] 或 [ˈlɪnʊks],"丽娜克斯" 或 "李扭克斯"都可以。

    +
  • +
  • +

    LaTeX: 正确的发音是 [ˈleɪtɛk] 或 [ˈleɪtɛx] 或 [ˈlɑːtɛx] 或 [ˈlɑːtɛk],即"雷泰克" 或 "拉泰克"。

    +
  • +
  • +

    GNOME: 念法可以是 [ɡˈnoʊm] 或 [noʊm],即"格弄姆" 或 "弄姆"。

    +
  • +
  • +

    App: 应该念为 [ˈæp],即 "阿破"。

    +
  • +
  • +

    null: 正确的发音是 [nʌl],即"闹"。

    +
  • +
  • +

    jpg: 应该念为 [ˈdʒeɪpɛɡ],而不是 "勾屁记",应该是 "zhei派个"。

    +
  • +
  • +

    WiFi: 正确的发音是 [ˈwaɪfaɪ],即"歪fai"。

    +
  • +
  • +

    mobile: 念法可以是 [moˈbil] 或 [ˈmoˌbil] 或 [ˈməubail],即"膜拜哦" 或 "牟bou"。

    +
  • +
  • +

    integer: 正确的发音是 [ˈɪntɪdʒə],而不是 "阴太阁儿",应该是 "音剃摺儿"。

    +
  • +
  • +

    cache: 应该念为 [kæʃ],而不是 "卡尺",即"喀什"。

    +
  • +
  • +

    @: 应该念为 "at"。

    +
  • +
  • +

    Tumblr: 应该念为 "Tumbler",而不是 "贪不勒"。

    +
  • +
  • +

    nginx: 正确的发音是 "Engine X",应该是 "恩静 爱克斯"。

    +
  • +
  • +

    Apache: 应该念为 [əˈpætʃiː],即"阿趴气"。

    +
  • +
  • +

    Lucene: 正确的发音是 [ˈluːsin],即"鲁信"。

    +
  • +
  • +

    MySQL: 应该念为 [maɪ ˌɛskjuːˈɛl] 或 [maɪ ˈsiːkwəl],可以是 "买S奎儿" 或 "买 吸扣"。

    +
  • +
  • +

    Exposé: 念法可以是 [ɛksˈpəʊzeɪ],重音在Z上。

    +
  • +
  • +

    RFID: 官方念法是四个字母分开读 "R F I D"。

    +
  • +
  • +

    JSON: 应该念为 "jason",即"zhei森"。

    +
  • +
  • +

    Processing: 重音在 "Pro" 上。

    +
  • +
  • +

    avatar: 正确的发音是 [ˌævə'tɑr],即"艾瓦塌儿"。

    +
  • +
+

后记

+

虽然许多的词汇常常被错误发音,但在中国遵守拼音原则是入乡随俗的一种表现,且往往并没有所谓的官方读法,不必太过于纠结100%纯正的读法。

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-aria2/index.html b/public/about-aria2/index.html new file mode 100644 index 0000000..73fd6e5 --- /dev/null +++ b/public/about-aria2/index.html @@ -0,0 +1,253 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:Aria2各平台使用指南

+ + + + + + +
+

前言 Aria2是一款开源、跨平台的命令行界面下载管理器,常常被各种下载器软件使用。

+

介绍

+

Aria2是一款开源、跨平台的命令行界面下载管理器,支持的下载协议有:HTTP、HTTPS、FTP、Bittorrent 和 Metalink。​它以高效、轻量和灵活著称,适用于需要批量下载、自动化任务或远程控制的用户。

+

Aria2 有以下几个特点:

+
    +
  • 多连接下载:可以从多个来源/协议下载文件并尝试利用您的最大下载带宽,真正加快您的下载体验;
  • +
  • 轻量:不需要太多内存和 CPU 时间;
  • +
  • 全功能的 BitTorrent 客户端:BitTorrent 客户端的所有功能都可用,,如 DHT、PEX、加密、Magnet URI、网络播种、选择性下载、本地对等发现和 UDP 跟踪器;
  • +
  • 支持Metalink:支持 Metalink 下载描述格式。 在下载中使用 Metalink 数据块的校验和自动验证下载的数据部分;
  • +
  • 远程控制:支持 RPC 接口来控制 aria2 进程。 支持的接口是 JSON-RPC(通过 HTTP 和 WebSocket)和 XML-RPC。
  • +
+

Aria2 原生使用命令行工具进行操作,为了更方便控制我们可以使用其他开源的面板配合本体,如AriaNg或者webui-aria2

+

Windows

+

首先下载aria2-1.37.0-win-64bit-build1.zip,将下载好的文件解压并放到你喜欢的目录下,设置系统环境变量,类似D:\DATA\Data\AriaNg-1.3.10-AllInOne,随后即可在 CMD 中使用 Aria2 。

+

随后可以安装 AriaNg 前端,AriaNg 使用纯 html & javascript 开发, 所以其不需要任何编译器或运行环境.

+

ariang-1

+

AriaNg 现在提供三种版本, 标准版、单文件版和 AriaNg Native. 标准版适合在 Web 服务器中部署, 提供资源缓存和按需加载的功能. 单文件版适合本地使用, 您下载后只要在浏览器中打开唯一的 html 文件即可. AriaNg Native 同样适合本地使用, 并且不需要使用浏览器.这里建议使用单文件版或者Native版。

+

单文件版(AllinOne) +Native版

+

Arch linux

+

首先安装aria2本体:

+
paru -S aria2
+
+

随后创建配置文件

+
nano /home/<you-username>/.config/aria2/aria2.conf
+
+

内容为

+
enable-rpc=true
+rpc-listen-all=true
+rpc-allow-origin-all=true
+rpc-listen-port=6800
+continue=true
+dir=/home/<you-username>/Downloads
+input-file=/home/<you-username>/.config/aria2/aria2.session
+save-session=/home/<you-username>/.config/aria2/aria2.session
+save-session-interval=60
+
+

保存退出;随后创建守护进程以便开机自启动:

+
nano ~/.config/systemd/user/aria2.service
+
+

写入:

+
[Unit]
+Description=Aria2 Daemon
+After=network.target
+
+[Service]
+ExecStart=/usr/bin/aria2c --conf-path=/home/<you-username>/.config/aria2/aria2.conf
+Restart=on-failure
+
+[Install]
+WantedBy=default.target
+
+

在更新配置文件和服务文件后,执行以下命令以重启服务:​

+
systemctl --user daemon-reload
+systemctl --user enable aria2.service
+systemctl --user start aria2.service
+
+

使用以下命令检查服务状态:​

+
systemctl --user status aria2.service
+
+

浏览器插件

+

如果你想让其直接接管浏览器下载,可以使用以下几种浏览器插件:

+

Chrome 浏览器

+
    +
  • Aria2 Explorer是一款功能强大的扩展,能够自动拦截浏览器的下载任务,并通过 JSON-RPC 接口将其导出到 Aria2 进行下载。 ​
  • +
  • Aria2 for Chrome
  • +
+

Firefox 浏览器

+ +

通用版

+ +

🔗

+

附带 aria2 的服务端应用

+ +
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-baci/index.html b/public/about-baci/index.html new file mode 100644 index 0000000..51cfb6d --- /dev/null +++ b/public/about-baci/index.html @@ -0,0 +1,655 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:Baci实验笔记

+ + + + + + +
+

前言 ​BACI是一个简化的并发程序模拟器,这里对其语法与运行环境进行说明。

+ +

​BACI(Ben-Ari Concurrent Interpreter)由计算机科学家 M. Ben-Ari 开发,是一个用于教学目的的并发程序模拟器,提供了一个简化的编程环境,使学习者能够编写、编译和执行并发程序,从而深入理解进程同步、互斥、信号量等核心概念。

+

官方指南

+

BACI C−− User’s Guide:详细介绍了 C−− 编译器(bacc)与 PCODE 解释器(bainterp)的使用方法、语法说明及示例程序。该指南包含编译命令、信号量、监视器等并发原语介绍。 这里对官方文档进行了汉化:

+
+

作者:Bill Bynum/Tracy Camp 威廉玛丽学院/科罗拉多矿业学院 2002年11月5日

+
+

目录

+
1. 引言
+2. C-- 编译器语法
+3. 并发结构
+   3.1 cobegin 块
+   3.2 信号量
+      3.2.1 初始化信号量
+      3.2.2 p (或 wait) 和 v (或 signal) 函数
+      3.2.3 信号量使用示例
+   3.3 管程
+      3.3.1 条件变量
+      3.3.2 waitc 和 signalc 函数
+      3.3.3 立即恢复要求
+      3.3.4 管程示例
+   3.4 其他并发结构
+      3.4.1 atomic 关键字
+      3.4.2 void suspend( void );
+      3.4.3 void revive( int process_number );
+      3.4.4 int which_proc( void );
+      3.4.5 int random( int range );
+4. 内置字符串处理函数
+   4.1 void stringCopy(string dest, string src);
+   4.2 void stringConcat(string dest, string src);
+   4.3 int stringCompare(string x, string y);
+   4.4 int stringLength(string x);
+   4.5 int sscanf(string x, rawstring fmt,...);
+   4.6 void sprintf(string x, rawstring fmt,...);
+5. 使用 BACI C-- 编译器和 PCODE 解释器
+6. 示例程序和输出
+
+

1. 引言

+

本文档旨在简要描述 C-- BACI 编译器和并发 PCODE 解释器程序,并说明如何使用它们。C-- 编译器首先将用户程序编译成一种称为 PCODE 的中间目标代码,然后由解释器执行。C-- 编译器支持二进制和计数信号量以及 Hoare 管程。解释器模拟并发进程执行。

+

BACI 系统程序:

+ + + + + + + + +
程序功能相关文档
baccBACI C-- 到 PCODE 编译器本指南 (cmimi.ps)
bapasBACI Pascal 到 PCODE 编译器guidepas.ps
bainterp命令行 PCODE 解释器cmimi.ps, guidepas.ps, disasm.ps
baguiPCODE 解释器的图形用户界面(仅限 UNIX 系统)guiguide.ps
badisPCODE 反编译器disasm.ps
baarPCODE 归档程序sepcomp.ps
baldPCODE 链接器sepcomp.ps
+

Pascal 版本的编译器和解释器最初是 M. Ben-Ari 编写的程序中的过程,基于 Niklaus Wirth 的原始 Pascal 编译器。程序源代码作为附录包含在 Ben-Ari 的著作《并发编程原理》中。BACI 编译器和解释器的原始版本就是从该源代码创建的。最终,Pascal 编译器和解释器被分成两个独立的程序,并开发了 C-- 编译器,用于将用 C++ 的受限子集编写的源程序编译成可由解释器执行的 PCODE。

+

下面将解释 C-- 编译器的语法。本指南仅适用于 C-- 编译器,不适用于 BACI 并发 Pascal 编译器。对 Pascal 编译器感兴趣的用户应参考其用户指南(见文件 guidepas.ps)。

+

2. C-- 编译器语法

+
    +
  1. +

    如同 C++,注释可以用 '/' 和 '/' 或 '//' 来界定。

    +
  2. +
  3. +

    除了标准输入和输出外没有其他文件:cout、cin 和 endl 在 C-- BACI 中的行为与标准 C++ 一致。主程序必须具有以下形式之一:

    +
    int main()
    +void main()
    +main()
    +
    +
  4. +
  5. +

    C-- BACI 中唯一可用的简单 C/C++ 类型是 int 和 char。还有其他与并发控制相关的类型,将在下面讨论。

    +

    所有变量必须在它们出现的代码块开头声明。特别是,for 循环的索引变量不能在循环头中声明,而必须在包含该 for 循环的块的开头声明。

    +
  6. +
  7. +

    支持 string 类型。声明字符串时,必须指定字符串的长度。以下声明定义了一个长度为 20 的字符串:

    +
    string[20] string_name;
    +
    +

    长度说明符应该是字符串应具有的字符数,不应包括终止字节的空间。编译器负责为终止字节保留空间。长度说明符必须是字面常量或程序常量。

    +

    在函数声明中,string 关键字用于声明 string 类型的参数:

    +
    void proc(string formal_parm)
    +
    +

    此声明断言 formal_parm 的类型为 string[n],其中 n 为某个正值。string 类型的参数是通过引用传递的。不执行字符串溢出检查。

    +
  8. +
  9. +

    支持任何有效类型的数组。数组声明遵循通常的 C 语法:

    +
    element_type arrayname[index1][index2][index3]...[indexN];
    +
    +
  10. +
  11. +

    C-- BACI 支持关键字 typedef。例如,要使变量名 length 成为 int 的同义词:

    +
    typedef int length;
    +
    +
  12. +
  13. +

    支持简单类型的常量 (const):

    +
    const int m = 5;
    +
    +
  14. +
  15. +

    在声明 int 和 char 类型的变量时,支持初始化器。初始化器的值必须是字面量或程序常量:

    +
    const int m = 5;
    +int j = m;
    +int k = 3;
    +char c = 'a';
    +
    +
  16. +
  17. +

    支持过程和函数。适用标准作用域规则。支持递归。参数声明为传值或传引用:

    +
    int afunc(int a, /* 传值 */
    +        int& b) /* 传引用 */
    +
    +

    每个程序必须有一个 int 或 void 类型的 main() 函数,并且该函数必须是源文件中的最后一个函数。执行从 main() 的调用开始。

    +
  18. +
  19. +

    可执行语句包括 if-else、switch/case、for、while、do-while、break 和 continue。这些语句的语法与标准 C/C++ 相同。代码的括号也是标准的,即 { ... }。

    +
  20. +
  21. +

    支持标准 C/C++ 文件包含:

    +
    #include < ... >
    +#include " ... "
    +
    +

    两种包含语句风格具有相同的语义,因为没有"系统"包含目录。

    +
  22. +
  23. +

    支持用于定义外部变量的 extern 关键字。外部变量可以是任何有效的 C-- 类型。外部变量不能使用初始化器。extern 关键字只能出现在全局("外部")级别。典型示例:

    +
    extern int i;
    +extern char a[20];
    +extern string[30] b;
    +// 不允许初始化器 ----> extern int i = 30;
    +// (如果有初始化,必须在 i 定义的地方进行)
    +extern int func(int k);
    +extern monitor monSemaphore { // 见第 3 节。这里只需给出
    +  void monP();              // 管程的外部可见细节
    +  void monV();
    +}
    +
    +

    使用 bacc 编译包含外部引用的源文件时,必须使用 -c 选项。有关使用外部变量的更多信息,请参阅 BACI 系统分离编译指南。

    +
  24. +
+

3. 并发结构

+

3.1 cobegin 块

+

C-- 进程是一个 void 函数。在 BACI 系统中,"并发进程"一词与"并发线程"一词同义。要并发运行的进程列表封装在一个 cobegin 块中。这种块不能嵌套,必须出现在主程序中。

+
cobegin {
+  proc1(...); proc2(...); ... ; procN(...);
+}
+
+

列出的过程中的 PCODE 语句由解释器以任意的"随机"顺序交错执行,因此,包含 cobegin 块的同一程序的多次执行将表现为非确定性的。主程序被挂起,直到 cobegin 块中的所有进程终止,此时主程序在块结尾后的语句处恢复执行。

+

3.2 信号量

+

解释器有一个预先声明的 semaphore 类型。也就是说,C-- 中的信号量是一个非负整数变量(见下面的定义),只能以受限方式访问。二进制信号量,即只取值 0 和 1 的信号量,由 semaphore 类型的 binarysem 子类型支持。在编译和执行过程中,编译器和解释器强制限制 binarysem 变量只能取值 0 或 1,而 semaphore 类型只能是非负的。

+

3.2.1 初始化信号量

+

只有在定义信号量变量时才允许对其赋值。例如,以下任一声明都是有效的:

+
semaphore s = 17;
+binarysem b = 0;
+
+

内置过程:

+
initialsem(semaphore, integer_expression);
+
+

是在运行时初始化任一类型信号量的唯一可用方法。在调用中,integer_expression 可以是计算结果为整数且对信号量类型有效的任何表达式(semaphore 类型为非负,binarysem 类型为 0 或 1)。例如,以下两个 initialsem 调用显示了初始化上述两个信号量的另一种方式:

+
initialsem(s, 17);
+initialsem(b, 0);
+
+

3.2.2 p (或 wait) 和 v (或 signal) 函数

+

p 函数(或同义的 wait)和 v 函数(或同义的 signal)由并发执行的进程用于同步它们的操作。这些函数为用户提供了更改信号量值的唯一方式。

+

这两个函数的原型如下:

+
void p(semaphore& s);
+
+

或等效地:

+
void wait(semaphore& s);
+
+

以及:

+
void v(semaphore& s);
+
+

或等效地:

+
void signal(semaphore& s);
+
+

每个函数的信号量参数显示为引用参数,因为函数会修改信号量的值。

+

p 和 v 函数调用的语义如下:

+

p(sem);

+
    +
  • 如果 sem > 0,则将 sem 减 1 并返回,允许 p 的调用者继续。
  • +
  • 如果 sem = 0,则使 p 的调用者休眠。这些操作是原子的,即它们是不可中断的,从开始到结束执行。
  • +
+

v(sem);

+
    +
  • 如果 sem = 0 且一个或多个进程正在 sem 上休眠,则唤醒其中一个进程。如果没有进程在 sem 上等待,则将 sem 加一。在任何情况下,v 的调用者都被允许继续。这些操作是原子的,即它们是不可中断的,从开始到结束执行。
  • +
  • v 的某些实现要求按 FIFO 顺序唤醒等待信号量的进程(队列信号量),但 BACI 符合 Dijkstra 的原始提议,在信号到达时随机选择要重新唤醒的进程。
  • +
+

3.2.3 信号量使用示例

+

为帮助解释信号量的使用,我们提供以下简短示例:

+
BACI System: C-- to PCODE Compiler, 09:24 2 May 2002
+Source file: semexample.cm Sun Apr 28 20:40:12 2002
+line pc
+1 0 // C-- 信号量使用示例
+2 0
+3 0 semaphore count; // 一个"通用"信号量
+4 0 binarysem output; // 一个二进制(0 或 1)信号量,用于解除输出混乱
+5 0
+6 0 void increment()
+7 0 {
+8 0 p(output); // 获取对标准输出的独占访问权
+9 2 cout << "before v(count) value of count is " << count << endl;
+10 6 v(output);
+11 8 v(count); // 增加信号量
+12 10 } // increment
+13 11
+14 11 void decrement()
+15 11 {
+16 11 p(output); // 获取对标准输出的独占访问权
+17 13 cout << "before p(count) value of count is " << count << endl;
+18 17 v(output);
+19 19 p(count); // 减少信号量(或停止 -- 见手册文本)
+20 21 } // decrement
+21 22
+22 22 main()
+23 23 {
+24 23 initialsem(count,0);
+25 26 initialsem(output,1);
+26 29 cobegin {
+27 30 decrement(); increment();
+28 36 }
+29 37 } // main
+
+

该程序使用两个信号量。一个信号量 count 属于 semaphore 类型,这向 BACI 系统表明该信号量将被允许具有任何非负值。两个并发过程 increment 和 decrement 通过 count 信号量相互"发送信号"。另一个信号量 output 属于 binarysem 类型,这向 BACI 系统表明该信号量应始终具有值 0 或 1;任何其他值都会导致运行时异常。该信号量用于防止两个并发执行的过程 increment 和 decrement 的输出混合在一起。

+

我们使用以下命令生成上述编译器列表:

+
prompt% bacc semexample
+Pcode and tables are stored in semexample.pco
+Compilation listing is stored in semexample.lst
+
+

然后可以使用 BACI PCODE 解释器执行 semexample.pco 文件:

+
prompt% bainterp semexample
+Source file: semexample.cm Sun Apr 28 20:40:12 2002
+Executing PCODE ...
+before v(count) value of count is 0
+before p(count) value of count is 1
+
+

这是程序可能产生的三种可能输出之一。另外两种可能的程序输出是:

+
prompt% bainterp semexample
+Source file: semexample.cm Sun Apr 28 20:40:12 2002
+Executing PCODE ...
+before p(count) value of count is 0
+before v(count) value of count is 0
+
+
prompt% bainterp semexample
+Source file: semexample.cm Sun Apr 28 20:40:12 2002
+Executing PCODE ...
+before v(count) value of count is 0
+before p(count) value of count is 0
+
+

有兴趣的读者可能会发现,提供这三种程序输出生成方式的解释,并证明这三种输出是唯一可能的输出,是很有指导意义的。

+

3.3 管程

+

支持 Hoare 提出的管程概念,但有一些限制。管程是一个 C-- 块,类似于由过程或函数定义的块,但具有一些额外的属性。管程块中的所有函数都是可见的(即可从块外部调用的入口过程),但管程变量在块外部不可访问,并且只能由管程函数访问。

+

在 C-- 中,管程只能在最外层、全局级别声明。管程不能嵌套。管程可以选择在最后一个块中有一个 init{} 块,用于初始化管程变量的值。这段代码在主程序启动时运行。

+

管程块的只有一个过程或函数可以在任何时候执行。这一特性使得可以使用管程来实现互斥。使用管程控制并发是有优势的,因为所有控制并发的代码都位于管程中,而不是像使用信号量那样广泛分布在调用者中。

+

管程的过程和函数使用三种结构来控制并发:条件变量、waitc(等待条件)和 signalc(表示条件)。

+

3.3.1 条件变量

+

条件变量只能在管程中定义,因此只能由管程的进程访问。条件变量实际上从不"有"值;它是等待的地方或信号的东西。管程进程可以通过 waitc 和 signalc 调用等待条件成立或表示给定条件现在成立。

+

3.3.2 waitc 和 signalc 函数

+

waitc 和 signalc 调用具有以下语法和语义:

+
void waitc(condition cond, int prio);
+
+

管程进程(因此,也是调用管程进程的外部进程)被阻塞并被分配优先级 prio 以便被重新唤醒(见下面的 signalc)。请注意,这种阻塞操作允许另一个管程进程执行,如果有的话。

+
void waitc(condition cond);
+
+

此调用具有与上面的 waitc 调用相同的语义,但等待被分配默认优先级 10。

+
void signalc(condition cond);
+
+

唤醒在 cond 上等待的、具有最小(最高)优先级的某个进程;否则,不执行任何操作。请注意,这与信号量 v 或 signal 完全不同,因为如果没有人等待,signalc 是一个空操作,而 v(sem) 在没有人等待时会增加 sem,从而在将来的 p(sem) 发生时"记住"该操作。

+

优先级方案可用于实现重新唤醒等待者的 FIFO 规则。如果每个管程进程都增加与当前分配给条件的优先级相关联的管程变量,那么对该条件的连续 signalc 将按照 FIFO 顺序唤醒休眠进程。

+

C-- 编译器提供了一个 int 函数 empty(cond),如果条件 cond 的队列中没有进程等待,则返回 1,否则返回 0。

+

3.3.3 立即恢复要求

+

这是指刚刚被发送信号的条件上等待的进程应该优先于新调用管程进程(那些想要"从顶部"进入的进程)重新进入管程的要求。该要求基于这样的假设:刚刚被发送信号的条件比新进入管程的情况具有更"紧急"的业务要执行。立即恢复要求在 BACI 中通过挂起条件的发送者并随机选择一个具有适当优先级的条件等待者来运行来实现。因此,signalc 条件的管程过程通常将其作为最后一条指令。

+

当被 signalc 重新唤醒的进程离开管程时,在发出 signalc 调用后被挂起的在管程中执行的进程被允许优先于尝试"从顶部"进入管程的进程恢复在管程中的执行。

+

3.3.4 管程示例

+

以下通过管程实现通用信号量的示例说明了管程语法:

+
monitor monSemaphore {
+  int semvalue;
+  condition notbusy;
+  void monP()
+  {
+    if (!semvalue)
+      waitc(notbusy);
+    else
+      semvalue--;
+  }
+  void monV()
+  {
+    if (empty(notbusy))
+      semvalue++;
+    else
+      signalc(notbusy);
+  }
+  init{ semvalue = 1; }
+} // monSemaphore 管程结束
+
+

3.4 其他并发结构

+

BACI C-- 提供了几个低级并发结构,可用于创建新的并发控制原语:这些函数可用于创建"公平"(FIFO)队列信号量。实现这一点的代码超出了本用户指南的范围。

+

3.4.1 atomic 关键字

+

如果一个函数被定义为 atomic,那么该函数是不可抢占的。解释器不会用上下文切换中断一个原子函数。这为用户提供了定义新原语的方法。以下程序说明了如何定义 test_and_set 原语并使用它来强制互斥:

+
atomic int test_and_set(int& target) {
+  int u;
+  u = target;
+  target = 1;
+  return u;
+}
+
+int lock = 0;
+
+void proc(int id) {
+  int i = 0;
+  while(i < 10) {
+    while (test_and_set(lock)) /* wait */ ;
+    cout << id;
+    lock = 0;
+    i++;
+  }
+}
+
+main() {
+  cobegin { proc(1); proc(2); proc(3); }
+}
+
+

3.4.2 void suspend(void);

+

suspend 函数使调用线程休眠。

+

3.4.3 void revive(int process_number);

+

revive 函数重新激活给定编号的进程。

+

3.4.4 int which_proc(void);

+

which_proc 函数返回当前线程的进程编号。

+

3.4.5 int random(int range);

+

random 函数返回一个在 0 到 range - 1(包含)之间"随机选择"的整数。它使用与解释器使用的不同的随机数生成器流;也就是说,random() 调用不会影响解释器执行。

+

4. 内置字符串处理函数

+

4.1 void stringCopy(string dest, string src);

+

stringCopy 函数将 src 字符串复制到 dest 字符串中。不执行字符串溢出检查。例如:

+
string[20] x;
+...
+stringCopy(x,"Hello, world!");
+stringCopy(x,"");
+
+

将把字符串 x 初始化为一个众所周知的值。第二个 stringCopy 将字符串 x 重置为零长度字符串。

+

4.2 void stringConcat(string dest, string src);

+

stringConcat 函数将 src 字符串连接到 dest 的末尾。不执行字符串溢出检查。

+

4.3 int stringCompare(string x, string y);

+

stringCompare 函数与 C 字符串库中的 strcmp 函数具有相同的语义:如果字符串 x 按字典顺序在字符串 y 之后,则返回正数;如果字符串相等,则返回零;如果字符串 x 按字典顺序在字符串 y 之前,则返回负数。

+

4.4 int stringLength(string x);

+

stringLength 函数返回字符串 x 的长度,不包括终止字节。

+

4.5 int sscanf(string x, rawstring fmt,...);

+

与"真正的" sscanf 一样,sscanf 函数根据格式字符串 fmt 扫描字符串 x,将扫描到的值存储到参数列表中提供的变量中,并返回扫描到的项目数。仅支持真正的 sscanf 的 %d、%x 和 %s 格式说明符。还支持 BACI 独有的附加格式说明符 %q(带引号的字符串)。对于此说明符,所有由一对双引号(")分隔的字符都将被扫描到相应的字符串变量中。当在格式字符串中遇到 %q 说明符时,如果要扫描的字符串中的下一个非空白字符不是双引号,则 %q 扫描失败,并且字符串的扫描终止。

+

格式字符串后面出现的变量是引用变量(即,不需要 & 符号)。

+

在以下示例中,sscanf 调用返回的 i 值将为 4,存储在变量 j 中的值将为 202,存储在字符串 x 中的字符串值将为 alongstring,存储在变量 k 中的值将为 0x3c03,存储在字符串 y 中的字符串将为 a long string。

+
string[50] x,y;
+int i,j,k;
+stringCopy(x,"202 alongstring 3c03 \"a long string\"");
+i = sscanf(x,"%d %s %x %q",j,x,k,y);
+
+

4.6 void sprintf(string x, rawstring fmt,...);

+

与 C 库中的"真正的" sprintf 函数一样,sprintf 函数使用格式字符串 fmt 和格式字符串后面的变量创建存储在变量 x 中的字符串。

+

支持 %d、%o、%x、%X、%c 和 %s 格式说明符,其全部功能与真正的 sprintf 相同。此外,%q 格式说明符将在输出字符串中插入带双引号的字符串。%q 格式说明符等同于 "%s" 说明符。

+

例如,在以下代码片段中:

+
string[80] x;
+string[15] y,z;
+stringCopy(y,"alongstring");
+stringCopy(z,"a long string");
+sprintf(x,".%12d. .%-20s. .%q. .%08X.",202,y,z,0x3c03);
+
+

字符串 x 变为:

+
. 202. .alongstring . ."a long string". .00003C03.
+
+

5. 使用 BACI C-- 编译器和 PCODE 解释器

+

使用 BACI 系统执行程序有两个步骤。

+
    +
  1. +

    编译 ".cm" 文件以获取 ".pco" 文件。

    +

    用法:bacc [可选标志] 源文件名

    +

    可选标志:

    +
    -h 显示此帮助
    +-c 创建一个 .pob 目标文件以便后续链接
    +
    +

    源文件名是必需的。如果缺少,您将被提示输入。如果您不提供,将附加文件后缀 ".cm"。

    +
  2. +
  3. +

    解释 ".pco" 文件以执行程序

    +

    用法:baininterp [可选标志] pcode文件名

    +

    可选标志:

    +
    -d 进入调试器,单步执行,设置断点
    +-e 在进入每个进程时显示活动记录 (AR)
    +-x 在退出每个进程时显示 AR
    +-t 宣布进程终止
    +-h 显示此帮助
    +-p 显示正在执行的 PCODE 指令
    +
    +

    PCODE 文件名是必需的。如果缺少,您将被提示输入。文件后缀 ".pco" 将附加到您给出的文件名。

    +
  4. +
+

每次用 bainterp 执行 .pco 文件时,不必重新编译源文件。有一个 shell 脚本 baccint,它将为您调用编译器,然后调用解释器。它会将您给它的选项(见上文)传递给解释器。

+

6. 示例程序和输出

+

以下列表由 C-- BACI 编译器生成。行号右侧的数字是开始该行的指令的 PCODE 偏移量。BACI 编译器从文件 "incremen.cm" 创建此列表。该列表被放置在文件 "incremen.lst" 中。还创建了一个 "incremen.pco" 文件;此文件由解释器使用。

+
BACI System: C-- to PCODE Compiler, 09:24 2 May 2002
+Source file: incremen.cm Wed Oct 22 21:18:02 1997
+line pc
+1 0 const int m = 5;
+2 0 int n;
+3 0
+4 0 void incr(char id)
+5 0 {
+6 0 int i;
+7 0
+8 0 for(i = 1; i <= m; i = i + 1)
+9 14 {
+10 14 n = n + 1;
+11 19 cout << id << " n =" << n << " i =";
+12 25 cout << i << " " << id << endl;
+13 31 }
+14 32 }
+15 33
+16 33 main()
+17 34 {
+18 34 n = 0;
+19 37 cobegin
+20 38 {
+21 38 incr( 'A'); incr( 'B' ); incr('C');
+22 50 }
+23 51 cout << "The sum is " << n << endl;
+24 55 }
+
+

以下列表由 BACI 解释器生成。解释器执行编译到文件 "incremen.pco" 中的程序。

+
Source file: incremen.cm Wed Oct 22 21:18:02 1997
+Executing PCODE ...
+C n =1 i =A n =1 C2 i =
+1 A
+C n =4 i =2 C
+B n =A n =5 i =24 A
+i =1 B
+AC n = n =6 i =3 C6 i =3
+A
+C n =7 i =4 C
+B n =9 i =2 BA n =8
+i =4 A
+C n =8 i =5 A n =9C
+i =5 A
+B n =10 i =3 B
+B n =11 i =4 B
+B n =12 i =5 B
+The sum is 12
+
+

linux环境运行baci

+
    +
  • 首先安装jdk和dos2unix
  • +
+
apt install jdk-openjdk  dos2unix
+
+
    +
  • 使用dos2unix转换格式
  • +
+
dos2unix ~/Git/java/baci/scripts/baci
+
+
    +
  • 编写baci脚本
  • +
+
#!/usr/bin/env bash
+# 定位到项目根目录(包含 javabaci 子目录的目录)
+BASEDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
+
+# 将 javabaci/bin(默认包类)和项目根目录(javabaci 包根)加入 classpath
+CLASSPATH="$BASEDIR/javabaci/bin:$BASEDIR"
+
+# 将所有参数原样传递给 java 运行
+exec java -cp "$CLASSPATH" "$@"
+
+
    +
  • 给baci授予可执行权限
  • +
+
chmod +x ~/Git/java/baci/scripts/baci
+
+
    +
  • 添加系统环境变量
  • +
+
fish_add_path ~/Git/java/baci/scripts
+
+
    +
  • 查看baci是否存在
  • +
+
which baci
+
+
    +
  • 现在即可编译运行
  • +
+
baci bacc ex3_1.cm
+baci bainterp ex3_1
+
+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-blog/index.html b/public/about-blog/index.html new file mode 100644 index 0000000..7089895 --- /dev/null +++ b/public/about-blog/index.html @@ -0,0 +1,319 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:个人博客搭建

+ + + + + + +
+

前言 个人博客的搭建具有许多的方案可以选择,本文介绍如何快速部署一个博客,并将其发布到公网。

+

前情回顾

+

在互联网冲浪的过程中,我们常常看到许多独立站点,他们往往是个人博客,有各种各样的主题样式;这些站点见证了互联网的发展历史。从最初的手工编写HTML页面,到后来的内容管理系统(CMS)如WordPress的兴起,再到如今流行的静态网站生成器(SSG),如Hugo,Hexo,Zola等等。

+

个人博客的定义是什么?私以为是域名+站点+原创内容三要素组成。当然,最重要的原创内容往往被忽视...

+
    +
  • 域名可以在Dynadot等平台购买,也可以申请如eu.orgus.kg等免费域名,目的是为了好记;
  • +
  • 站点可以在自己的服务器上使用动态的WordPress或者Halo来一键创建,也可以使用静态框架部署在PAAS平台上;
  • +
+

因此,整体成本应该是非常低的。

+

使用Halo快速搭建博客

+
    +
  • 首先你需要有一台自己的云服务器,建议在1核1G以上配置,并安装Debian系统;
  • +
  • 随后我们安装1panel,执行以下命令一键安装:
  • +
+
curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && sudo bash quick_start.sh
+
+
+

1panel依赖于docker,如果实现没有安装docker,脚本会帮你安装。

+
+
    +
  • +

    安装过程中选择好端口,随后即可使用http:<ip>:<port>:<安全入口>进入登录界面,并使用默认随机生成的密码进入面板。

    +
  • +
  • +

    进入之后我们可以看到里面有应用商店,在其中安装OpenRestyHalomysql,安装完毕后打开外部访问地址http://ip:8090,即可进入halo的后台,在其中写入文章并发布。

    +
  • +
+

但我们不能使用不安全的HTTP以及IP来访问博客;因此,我们需要一个域名指向我们的博客,例如本文的blog.dich.bid;可以在在Dynadot等平台购买域名,并托管到Cloudflare

+
    +
  • +

    随后可以在1panel的网站中创建一个反向代理,代理地址即为http://ip:8090,主域名为刚刚注册的域名前加blog或其他,如blog.xxx.com

    +
  • +
  • +

    创建完成后我们还需要配置TLS证书,在网站-HTTPS中添加证书,可以选择自签名证书正式或者通过Acme申请免费的Let's Encrypt证书。

    +
  • +
  • +

    配置完成后在Cloudflare的DNS解析界面创建一个A记录,将你的blog.xxx.com解析到你的服务器的IP

    +
  • +
  • +

    大功告成!现在你应该可以通过HTTPS域名访问自己的博客!

    +
  • +
+

使用Hugo框架构建博客

+

首先明确你需要的架构,一般有两种选择:

+
    +
  • 使用现有的架构,包括Hugo,Hexo,Zola,Astro等等;
  • +
  • 或者从头写一个框架,需要HTML/CSS/JS等知识;
  • +
+
+

可以在这个网站上面查看常见的框架与主题的显示效果

+
+
    +
  1. 安装Hugo:选择好你的框架与主题后(这里以hugo为例子),随后安装hugo以及对应的依赖:
  2. +
+
    +
  • Windows
  • +
+
# 打开以管理员模式运行的PowerShell,输入命令安装 Hugo Extended:
+winget install Hugo.Hugo.Extended
+
+
    +
  • Arch linux
  • +
+
paru -S hugo
+
+
    +
  • 检查版本
  • +
+
hugo version
+
+
    +
  1. 创建新的 Hugo 站点:选择一个文件夹打开命令行,执行:
  2. +
+
hugo new site myblog
+
+

该命令会在myblog文件夹下生成hugo的基础目录。

+
    +
  1. 安装主题,这里以hugo-blog-awesome主题为例:
  2. +
+
cd myblog
+git clone https://github.com/hugo-sid/hugo-blog-awesome.git themes/hugo-blog-awesome
+
+

并在hugo.toml顶层添加:

+
theme = "hugo-blog-awesome"
+
+

这样 Hugo 在构建时会从 themes/ 目录加载主题文件。后续可使用git pull获取主题更新。

+
+

你也可以直接用theme中的文件夹替换掉项目根目录下的同名文件夹,并再次修改。

+
+
    +
  1. 写入文章:使用 Hugo 提供的命令创建新文章:
  2. +
+
hugo new posts/hello-world.md
+
+

该命令会在content/posts/下生成 Markdown 文件,打开后修改title、date、tags等前缀然后撰写 Markdown 正文, Markdown 编辑器参考前文

+
+

注意md文章头部和正文之间得使用<!-- more -->隔断

+
+
    +
  1. 本地测试:在项目根目录运行:
  2. +
+
hugo server -D
+
+

然后在浏览器访问http://localhost:1313即可实时预览并查看更新效果。

+
    +
  1. +

    上传到GitHub:新建一个Github仓库,用Git连接并将Hugo项目的文件夹push上去;

    +
  2. +
  3. +

    使用PAAS平台部署:随后使用Vercel/Netlify等平台读取GitHub仓库并部署Hugo博客项目,并设置指向自己的域名,即设置一条CNAME记录。部署的时候可以让平台command运行部署也可以本地build之后直接上传public文件夹并在平台中指定。

    +
  4. +
+
+

当然,也可以使用GitHub Pages部署,详见官方文档

+
+

可选定制项

+

你想要的显示效果?

+
    +
  • 风格,包括命令行风格,极简风格,MD3风格等等;
  • +
  • 布局,是响应式还是传统布局?
  • +
+

你需要那些功能?

+
    +
  • 黑暗/白天模式切换;
  • +
  • 高斯模糊?动态取色?
  • +
  • PPT般的动效?
  • +
  • 访问人数和运行天数统计?
  • +
  • Tag分类和时间排序?
  • +
  • 搜索功能和RSS?
  • +
+

需要处理哪些外部依赖?

+
    +
  • 域名和paas平台?
  • +
  • 图床还是直接嵌入图片?
  • +
  • 是否需要自动编译?
  • +
  • 是否需要多平台发布?
  • +
  • 是否需要加密特定文章?
  • +
+

以上的功能和需求是否对SEO和界面相应时间造成影响?

+ + +
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-calling-cards/index.html b/public/about-calling-cards/index.html new file mode 100644 index 0000000..ea6acf8 --- /dev/null +++ b/public/about-calling-cards/index.html @@ -0,0 +1,224 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:流量卡购买与套路

+ + + + + + +
+

前言 由于临近升学,校园网不尽人意,因此许多小伙伴有了买一张流量卡的计划。本文以三大运营商为例,说明常见流量卡的套路与选择。

+ +

2019 年 6 月 6 日,工信部发布 4 张 5G 牌照,标志 5G 商用的开始,中国进入 5G 时代。回想过去数年,4G 降速、5G 提费的新闻屡见不鲜,而 5G 网络的落地应用,似乎离普通人依然遥远。对于普通人而言,昂贵的5G套餐资费依然没有流量卡香;那什么是流量卡呢?

+

一.什么是流量卡

+

流量卡本质上还是一张 SIM 卡,往往具有大流量、低月租的特征。互联网上有非常多不同运营商的「优惠套餐」,实则是不同卡商取名包装后的产物,卡商往往可以通过激活后赚取高额佣金获利,比如每年大学新生开学,校园里总有「运营商营业厅」摆摊甚至上门推销所谓「校园卡」,不少声称「超大流量」「长期套餐」,更有甚者,会搬出「校园网」来给涉世未深的大一小白们制造焦虑。

+

事实上,不管是「校园卡」还是网上卡商们大力吆喝的优惠流量卡,本质上都属于个人使用的电话卡。例如电信的优惠套餐,大都通过「电信星卡」套餐,再由当地运营商叠加优惠包(赠费或叠加流量包)包装而成。

+

二.为什么需要流量卡

+

普通卡大多有着长合约和固定归属地,不能轻易更换套餐,且套餐月租费用较高,特别是在5G推行时期,4G的资费不减反升,且速度有所下降。而流量卡动则100G往上,月租在50左右,且可以随时退卡。

+

三.流量卡基本原理

+

由于三大运营商处于半国企状态(自负盈亏),因此在长期亏损下不得不整一些牛马活采用一些策略,比如冗长的条款和隐藏极深的优惠套餐等等。而由于不同地区的经济发展状况不同,部分中西部地区的地区分公司业绩不佳,为了在短期内达到要求往往会和一些地区分销商进行合作,将本地区的电话卡改为优惠的套餐,从而吸引客户。注意:99%所谓的月租19、29等流量卡都是要先缴一笔较多的钱,进而每月返还一点点,实现长期上的低月租,运营商是要短期变现的!

+

那么,是不是我们就没有优惠了呢?其实相对于5元1G、40元10G的资费而言还是非常划算的。

+

四.分清流量卡和物联卡

+

部分小伙伴反映被物联卡坑了!这里我们一定要注意,诸如某宝某猫上面的9999G超级流量卡,usb接口的随身WiFi等等不出意外都是物联卡。

+

什么是物联卡?物联网设备往往只需要网络接入而不需要电话短信功能,也就不需要电话号码。为了防止滥用,同时降低成本,运营商往往会给这些设备制作「物联网卡」,也就是只具备上网功能的电话卡。为了便于物联网设备公司管理,运营商还会授权这些代理公司组建「流量池」,对池中每一张卡进行限速、流控等管理。

+

市面上绝大多数「随身 WiFi」自带的流量卡套餐,正是来自运营商授权公司的「自组流量池」。绝大多数物联卡商家,为了控制成本,会采取各种措施进行限制,而由于这一行业往往处于缺乏有效监管的灰色地带,这些限制大都不会被商家明确写出。

+

最常见的套路是虚标流量。由于这类物联网卡并没有手机号码,也就无法使用运营商官方渠道查询流量使用情况。商家自建流量管理后台,也就有了对数据做手脚的可乘之机。有些商家会将使用的流量按 1.5 倍甚至更高倍率计费,因此,你也许会发现自己的流量不那么「经用」。

+

另一个套路是流控,包括流量封顶和限速。网上销量相当高的某随身 WiFi 商家,电商平台可以看到不少次月开始卡慢、每日设置流量封顶的差评。比如,广告上打着「月享 1500G」,实际上也许每天限制使用 50G,达量往往会限速甚至封卡。

+

在市面上,流量池批发流量的价格大约是 0.1 元 / G,如果你看到了显著低于这个价格的流量,可能需要多斟酌一下是否可靠。

+

当然,也有正规厂商提供可信的流量池或与运营商直接合作的物联网卡,限制会少不少,不过难以买到。

+

五.购买流量卡需要注意的事项

+
    +
  • 靓号
  • +
+

大部分流量卡是不能选号的,因为这类具有优惠套餐的卡大多来自不同地区的前任买家,因此靓号数有限,总不能既有好的号码又有优惠套餐;而这就带来第二个问题:

+
    +
  • 号码绑定
  • +
+

作为信息时代的重要识别符,电话卡和身份证几乎同样重要,在前任主人信息意识不强的情况下,其大部分社交媒体、生活服务和各种网站的帐号都会遗留下来,这就需要我们去一一解绑;作者曾经买了一张宁夏的流量卡,结果通过验证和社工成功进入了前主人的微信和淘宝帐号,当然现在已经注销了;部分平台不支持注销的,只能继续使用前号;甚至有概率被前号主的债务人打电话催债;因此我们一定要小心谨慎;

+
    +
  • 归属地
  • +
+

由于前面所讲的原因,流量卡的归属地大部分是随机的,比如青海,宁夏等等;这样一来当别人打电话时会看到地址为中国宁夏之类,可能会误以为是诈骗电话;当然这样也有不被看到地址的好处,所谓各有优点。

+
    +
  • 信号
  • +
+

SIM卡本身对信号没有影响,除非氧化严重难以识别;真正影响体验的不只是手机基带,还有你所在地区中三大运营商的基站分布;因此,购买之前可以先查看一下你所在地区哪个运营商信号最好,从而对症下药。

+
    +
  • 副卡
  • +
+

有些小伙伴在买完流量卡后打算作为主力卡使用,那这样原先的卡套餐就没必要了,可以办理8元保号套餐,让号码可以继续使用。

+
    +
  • 流量
  • +
+

不少校园套餐,使用了定向流量(或区域流量),即仅可在指定APP使用或指定省(市)内使用,而非全国流量/通用流量。而宣传的额外流量往往以流量包形式给出,此流量包不同活动获得方式也不同;办完卡后进入营业厅的APP,流量可能不会马上出现,这是因为系统的延迟以及运营商的计时方式,有些卡需要在月初才能有全部的流量,后几天按百分比计算,下个月就正常了。

+
    +
  • 激活
  • +
+

注意要实名购卡,且收获地址要足够详细,会有专门的快递小哥和你线下激活,预充值,注意接收电话!

+
    +
  • 注销
  • +
+

每个运营商最多办5张电话卡,因此一个人一辈子最多只能从三大运营商办理一共15张卡,因此注销需谨慎;流量卡大部分可以线上异地注销,但也要仔细看清楚条款。

+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-cslearning/index.html b/public/about-cslearning/index.html new file mode 100644 index 0000000..fcb809e --- /dev/null +++ b/public/about-cslearning/index.html @@ -0,0 +1,367 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:计算机科学优质视频

+ + + + + + +
+

前言 CSdiy珠玉在前,为CS教育做出了极大贡献.这里分享一些优质的CS学习相关视频.

+

计算机组件发展历史

+ +

计算机组件原理

+ +

计算机博物志

+ +

计算机体系结构

+ +

操作系统 /计算机组成

+ +

编译相关 /软件分析

+ +

数据结构 /算法相关

+ +

计算机网络

+ +

程序语言 /编程语言

+ +

软件工程

+ +

数据库

+ +

并行程序设计

+ +

密码学

+ +

工具

+ +

其他

+ +

数学相关

+ +

哲学相关

+ +

人文/艺术/建筑/电影/社会学

+ +

综合

+ +

后记

+

待续...

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-frp/index.html b/public/about-frp/index.html new file mode 100644 index 0000000..c1a0408 --- /dev/null +++ b/public/about-frp/index.html @@ -0,0 +1,530 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:FRP使用指南

+ + + + + + +
+

前言 FRP (Fast Reverse Proxy) 是一个用Go语言开发的高性能反向代理应用,可以帮助您轻松地进行内网穿透,对外提供服务.

+

简介

+

FRP (Fast Reverse Proxy) 主要功能包括:

+
    +
  • 支持TCP、UDP、HTTP、HTTPS等多种协议
  • +
  • 支持Web服务、远程桌面、SSH、游戏服务器等多种应用场景
  • +
  • 提供加密和压缩功能,保证数据安全性
  • +
  • 支持多个客户端连接服务端,适用于复杂网络环境
  • +
+

FRP分为客户端(frpc)和服务端(frps)两部分:

+
    +
  • 服务端(frps): 部署在有公网IP的服务器上
  • +
  • 客户端(frpc): 部署在内网机器上,负责将内网服务映射到公网
  • +
+

安装

+

服务端安装

+

服务端需要部署在具有公网IP的服务器上。

+
    +
  1. 下载最新版本的FRP发行包:
  2. +
+
wget https://github.com/fatedier/frp/releases/download/v0.51.3/frp_0.51.3_linux_amd64.tar.gz
+
+
    +
  1. 解压文件:
  2. +
+
tar -xzvf frp_0.51.3_linux_amd64.tar.gz
+cd frp_0.51.3_linux_amd64
+
+
    +
  1. 现在您可以看到以下文件: +
      +
    • frps: 服务端可执行文件
    • +
    • frps.ini: 服务端配置文件
    • +
    • frpc: 客户端可执行文件
    • +
    • frpc.ini: 客户端配置文件
    • +
    +
  2. +
+

客户端安装

+

客户端需要安装在您的内网设备上,例如需要提供服务的电脑、服务器或IoT设备上。

+
    +
  • Linux/macOS
  • +
+

与服务端安装步骤相同,只需使用frpc程序和frpc.ini配置文件。

+
    +
  • Windows
  • +
+

同样下载Windows版本,解压后使用frpc.exe和frpc.ini。

+

配置

+

服务端配置

+

服务端配置文件为frps.ini,基本配置如下:

+
[common]
+# 服务端监听端口,用于与客户端建立连接
+bind_port = 7000
+
+# 用于身份验证的token
+token = yourSecureToken
+
+# 后台管理页面端口(可选)
+dashboard_port = 7500
+dashboard_user = admin
+dashboard_pwd = admin
+
+# 日志配置
+log_file = /var/log/frps.log
+log_level = info
+log_max_days = 3
+
+

客户端配置

+

客户端配置文件为frpc.ini,基本配置如下:

+
[common]
+# 服务端的IP地址或域名
+server_addr = x.x.x.x
+# 服务端的端口
+server_port = 7000
+# 认证token,需要与服务端匹配
+token = yourSecureToken
+
+# 示例:SSH服务代理
+[ssh]
+type = tcp
+local_ip = 127.0.0.1
+local_port = 22
+remote_port = 6000
+
+# 示例:HTTP服务代理
+[web]
+type = http
+local_ip = 127.0.0.1
+local_port = 80
+custom_domains = www.yourdomain.com
+
+

常用配置示例

+

1. 代理SSH服务

+
# frpc.ini
+[common]
+server_addr = x.x.x.x
+server_port = 7000
+token = yourSecureToken
+
+[ssh]
+type = tcp
+local_ip = 127.0.0.1
+local_port = 22
+remote_port = 6000
+
+

使用方法:ssh -p 6000 username@服务端IP

+

2. 代理HTTP网站

+
# frpc.ini
+[common]
+server_addr = x.x.x.x
+server_port = 7000
+token = yourSecureToken
+
+[web]
+type = http
+local_ip = 127.0.0.1
+local_port = 80
+custom_domains = www.yourdomain.com
+
+

在服务端需要将域名解析到服务端IP。

+

3. 代理HTTPS网站

+
# frpc.ini
+[common]
+server_addr = x.x.x.x
+server_port = 7000
+token = yourSecureToken
+
+[web-https]
+type = https
+local_ip = 127.0.0.1
+local_port = 443
+custom_domains = www.yourdomain.com
+
+

4. 代理远程桌面(RDP)

+
# frpc.ini
+[common]
+server_addr = x.x.x.x
+server_port = 7000
+token = yourSecureToken
+
+[rdp]
+type = tcp
+local_ip = 127.0.0.1
+local_port = 3389
+remote_port = 7001
+
+

启动与运行

+

服务端启动

+

Linux/macOS

+
./frps -c frps.ini
+
+

后台运行:

+
nohup ./frps -c frps.ini &
+
+

Windows

+

双击frps.exe或在命令行运行:

+
frps.exe -c frps.ini
+
+

客户端启动

+

Linux/macOS

+
./frpc -c frpc.ini
+
+

后台运行:

+
nohup ./frpc -c frpc.ini &
+
+

Windows

+

双击frpc.exe或在命令行运行:

+
frpc.exe -c frpc.ini
+
+

设置为系统服务

+

Linux (Systemd)

+
    +
  1. 创建服务文件 /etc/systemd/system/frps.service (服务端) 或 /etc/systemd/system/frpc.service (客户端)
  2. +
+

服务端示例 (frps.service):

+
[Unit]
+Description=Frp Server Service
+After=network.target
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/frps -c /etc/frps/frps.ini
+Restart=always
+RestartSec=5s
+
+[Install]
+WantedBy=multi-user.target
+
+

客户端示例 (frpc.service):

+
[Unit]
+Description=Frp Client Service
+After=network.target
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/frpc -c /etc/frpc/frpc.ini
+Restart=always
+RestartSec=5s
+
+[Install]
+WantedBy=multi-user.target
+
+
    +
  1. 启用并启动服务:
  2. +
+
# 服务端
+sudo systemctl enable frps
+sudo systemctl start frps
+
+# 客户端
+sudo systemctl enable frpc
+sudo systemctl start frpc
+
+
    +
  1. 查看服务状态:
  2. +
+
sudo systemctl status frps
+# 或
+sudo systemctl status frpc
+
+

Windows

+
    +
  1. 使用NSSM (Non-Sucking Service Manager) 创建服务: +
      +
    • 下载NSSM: http://nssm.cc/download
    • +
    • 安装服务:
      nssm.exe install frpc C:\path\to\frpc.exe -c C:\path\to\frpc.ini
      +
      +
    • +
    • 启动服务:
      nssm.exe start frpc
      +
      +
    • +
    +
  2. +
+

进阶功能

+

HTTPS支持

+

要支持HTTPS服务,需要在服务端添加配置:

+
# frps.ini
+[common]
+bind_port = 7000
+vhost_https_port = 443
+
+

客户端配置:

+
# frpc.ini
+[web]
+type = https
+local_ip = 127.0.0.1
+local_port = 443
+custom_domains = www.yourdomain.com
+
+

多路复用

+

使用多路复用可以减少连接数,提高性能:

+
# frpc.ini
+[common]
+server_addr = x.x.x.x
+server_port = 7000
+token = yourSecureToken
+# 启用多路复用
+tls_enable = true
+pool_count = 5
+
+

加密与压缩

+

增加数据传输的安全性:

+
# frpc.ini
+[common]
+server_addr = x.x.x.x
+server_port = 7000
+token = yourSecureToken
+# 启用加密和压缩
+use_encryption = true
+use_compression = true
+
+

负载均衡

+

通过配置多个后端服务实现负载均衡:

+
# frpc.ini
+[web]
+type = tcp
+local_ip = 127.0.0.1
+local_port = 80
+remote_port = 8080
+group = web
+group_key = 123456
+
+[web2]
+type = tcp
+local_ip = 127.0.0.1
+local_port = 8081
+remote_port = 8080
+group = web
+group_key = 123456
+
+

访问控制

+

限制客户端连接数量和带宽:

+
# frps.ini
+[common]
+bind_port = 7000
+token = yourSecureToken
+max_pool_count = 50
+max_ports_per_client = 10
+
+

常见问题排查

+

1. 连接被拒绝

+

问题: 客户端报错 "dial tcp x.x.x.x:7000: connect: connection refused"

+

解决方案:

+
    +
  • 检查服务端IP和端口是否正确
  • +
  • 确认服务端frps是否正在运行
  • +
  • 检查防火墙是否允许7000端口通信
  • +
+

2. 认证失败

+

问题: 客户端日志显示 "login to server failed: authentication failed"

+

解决方案:

+
    +
  • 确认客户端和服务端的token设置一致
  • +
  • 检查服务端日志是否有更多错误信息
  • +
+

3. 端口已被占用

+

问题: 服务端启动失败,提示 "bind: address already in use"

+

解决方案:

+
    +
  • 更改配置中的端口
  • +
  • 终止占用该端口的其他应用
  • +
  • 使用 netstat -tunlp | grep 端口号 查看占用该端口的进程
  • +
+

4. 无法访问代理服务

+

问题: 代理设置正确,但无法访问服务

+

解决方案:

+
    +
  • 检查本地服务是否正常运行
  • +
  • 确认local_ip和local_port设置正确
  • +
  • 使用 curl localhost:本地端口 测试本地服务
  • +
  • 检查服务端防火墙是否开放了remote_port
  • +
+

5. 代理连接不稳定

+

问题: 连接经常断开

+

解决方案:

+
    +
  • 增加心跳包频率,在[common]部分添加:
    heartbeat_interval = 30
    +heartbeat_timeout = 90
    +
    +
  • +
  • 启用多路复用和连接池
  • +
+

6. 域名解析失败

+

问题: 使用custom_domains配置,但无法通过域名访问

+

解决方案:

+
    +
  • 确保域名已正确解析到服务端IP
  • +
  • 检查frps.ini中是否配置了http/https的监听端口
  • +
  • 使用 dignslookup 命令验证域名解析
  • +
+

🔗

+ +
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-gfs/index.html b/public/about-gfs/index.html new file mode 100644 index 0000000..da067ca --- /dev/null +++ b/public/about-gfs/index.html @@ -0,0 +1,228 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:GFS项目考量笔记

+ + + + + + +
+

前言 最近nekoray项目归档,考量新的singbox前端时发现这个项目不错,不过在Arch linux中运行有一些小问题,这里做个总结。

+

安装最新版:

+

安装gui-for-singbox的时候发现仓库的1.9.2版本release被作者删除,无法安装,于是:

+
    +
  • 在AUR仓库中下载aur-gui-for-singbox.tar.gz,解压进入aur-gui-for-singbox目录;
  • +
  • 更改.SRCINFO文件,使其版本号为最新;
  • +
  • 使用makepkg -si构建并安装这个包,缺少的png图片可以直接下载并放进目录;
  • +
  • 如果有错误刷新密钥环(sudo pacman-key --refresh-keys);
  • +
+

无法打开/无法使用TUN模式:

+
    +
  • 安装成功,进入/opt/gui-for-singbox,运行sudo chown -R your_username:your_group /opt/gui-for-singbox,使其可以被非root用户启动;
  • +
  • 执行sudo setcap cap_net_bind_service,cap_net_admin,cap_dac_override=+ep /opt/gui-for-singbox/your_executable命令,并在设置-内核中点击盾牌-钥匙图标,使Tun模式可以有特权运行。
  • +
+

免密码运行TUN模式:

+
    +
  • 检查 polkit 服务是否正在运行
  • +
+
systemctl status polkit
+
+
    +
  • 若返回状态为除 active (running) 之外的结果,运行
  • +
+
sudo systemctl enable --now polkit
+
+
    +
  • 创建 polkit 策略
  • +
+
sudo vi /etc/polkit-1/rules.d/99-nopassword.rules
+
+
    +
  • 添加以下内容并保存退出
  • +
+
polkit.addRule(function (action, subject) {
+  if (
+    (action.id == "org.freedesktop.resolve1.set-domains" ||
+      action.id == "org.freedesktop.resolve1.set-default-route" ||
+      action.id == "org.freedesktop.resolve1.set-dns-servers") &&
+    subject.local &&
+    subject.active &&
+    subject.isInGroup("wheel")
+  ) {
+    return polkit.Result.YES;
+  }
+});
+
+
    +
  • 将当前用户添加至 wheel 组中,注意Debian 与衍生系统需要先创建 wheel 组,然后运行:
  • +
+
sudo usermod -G wheel 当前用户
+
+
    +
  • 重新加载 polkit 使更改生效
  • +
+
sudo systemctl restart polkit
+
+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-git/index.html b/public/about-git/index.html new file mode 100644 index 0000000..9e268c9 --- /dev/null +++ b/public/about-git/index.html @@ -0,0 +1,661 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:Git使用简明手册

+ + + + + + +
+

前言 Git,作为现代软件开发中不可或缺的版本控制工具,常常让初学者感到困惑。本文旨在介绍 Git 的全流程安装和基本使用,希望能够帮助新手更轻松地理解和掌握 Git 的基本概念和操作。

+

安装git

+
    +
  • +

    Windows:Git-download

    +
  • +
  • +

    Archlinux:sudo pacman -S git

    +
  • +
+

原理

+

一个Git仓库的目录里面包括工作目录(即我们要追踪的代码)以及.git目录(Git 在这里存储自己的数据)。Git 维护了三棵“树”:第一个是你的 工作目录,它持有实际文件;第二个是 暂存区(Index),它像个缓存区域,临时保存你的改动;最后是 HEAD,它指向你最后一次提交的结果。

+

git-tree

+

创建新仓库

+

首先我们需要得到一个Git仓库,一般有两种方法:

+
    +
  • 在本地初始化之后连接到远程;
  • +
  • 在远程创建后”下载“到本地。
  • +
+

方法一 +创建新文件夹,在你的项目目录中运行以下命令:

+
git init --initial-branch=main
+
+

这里设置默认仓库主分支名称为 main,避免因为 main/master 名称不同导致的推送问题。

+
+

Git目前默认的主分支为 master,和 github 默认分支 main 不同,这使得默认配置下 git 往往连接失败。除了创建的时候设定外还可以通过以下方法改变默认分支。

+
+
git config --global init.defaultBranch main  //将默认分支修改成main
+
+

方法二

+

克隆远端服务器上的仓库:

+
    +
  • HTTPS方法:git clone https://github.com/Dichgrem/script.git
  • +
  • 或者使用SSH方法:git clone git@github.com:Dichgrem/script.git
  • +
+
+

建议使用SSH方法,如果你使用HTTPS方法,则提交代码时需要手动输入用户名/密码,使用SSH方法则只需要在~/.ssh/config中配置即可。

+
+

配置

+

Git的设置文件为.gitconfig,它可以在用户主目录下(全局配置),也可以在项目目录下(项目配置)。

+
    +
  • 显示当前的Git配置
  • +
+
git config --list
+
+
    +
  • 编辑Git配置文件
  • +
+
git config -e [--global]
+
+
    +
  • 设置提交代码时的用户信息
  • +
+
git config [--global] user.name "[name]"
+git config [--global] user.email "[email address]"
+
+
    +
  • 设置大小写敏感(windows不区分大小写的解决办法)
  • +
+
git config core.ignorecase  false
+
+

连接远程仓库

+

连接到远程仓库并推送需要证明你有权写入仓库。早期Github可以使用密码认证,现在则使用密钥认证。

+
    +
  • 生成密钥:
  • +
+
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
+
+
    +
  • +

    生成的文件位于~/.ssh/config路径下,带.pub后缀的文件为公钥,不带.pub后缀的为私钥,使用cat ~/.ssh/id_rsa.pub将公钥添加到github/gitee的设置-SSH中。

    +
  • +
  • +

    随后使用 ssh-add 命令将生成的密钥添加到 SSH 代理中。

    +
  • +
+
ssh-add ~/.ssh/github_key
+ssh-add ~/.ssh/gitee_key
+
+
    +
  • ~/.ssh/config 文件中配置不同的主机别名以及相应的密钥文件。编辑该文件并添加内容,例如:
  • +
+
# GitHub repository 1
+
+Host github1
+
+    HostName github.com
+
+    User git
+
+    IdentityFile ~/.ssh/github_key
+
+# GitHub repository 2
+
+Host github2
+
+    HostName gitee.com
+
+    User git
+
+    IdentityFile ~/.ssh/gitee_key
+
+
    +
  • 连接到github:
  • +
+
ssh -T git@github.com
+
+
    +
  • 添加远程仓库:
  • +
+
git remote add origin <remote_repository_url>
+
+# 例如:git remote add origin git@github.com:Dichgrem/dichos.git
+
+
+

如果你运行git remote -v发现URL为HTTP格式则可以用下面的命令改为Git格式:

+
+
# 例如:git remote set-url origin git@github.com:Dichgrem/dichos.git
+
+

创建分支

+
git branch main
+
+

这将创建一个名为 main 的分支。

+
    +
  • 删除分支
  • +
+
git branch -d master
+
+
    +
  • 使用大写强制删除
  • +
+
git branch -D master
+
+

添加和提交

+

你可以提出更改(把它们添加到暂存区),使用如下命令:

+
git add <filename>
+git add *
+
+

这是 git 基本工作流程的第一步;使用如下命令以实际提交改动:

+
git commit -m "代码提交信息"
+# 例如:git commit -m "Initial commit"
+
+

现在,你的改动已经提交到了 HEAD,但是还没到你的远端仓库。

+
    +
  • 添加指定文件到暂存区
  • +
+
git add [file1] [file2] ...
+
+
    +
  • 添加指定目录到暂存区,包括子目录
  • +
+
git add [dir]
+
+
    +
  • 添加当前目录的所有文件到暂存区
  • +
+
git add .
+
+

添加每个变化前,都会要求确认

+
    +
  • 对于同一个文件的多处变化,可以实现分次提交
  • +
+
git add -p
+
+
    +
  • 删除工作区文件,并且将这次删除放入暂存区
  • +
+
git rm [file1] [file2] ...
+
+
    +
  • 停止追踪指定文件,但该文件会保留在工作区
  • +
+
git rm --cached [file]
+
+
    +
  • 改名文件,并且将这个改名放入暂存区
  • +
+
git mv [file-original] [file-renamed]
+
+

推送改动

+

你的改动现在已经在本地仓库的 HEAD 中了。执行如下命令以将这些改动提交到远端仓库:

+
git push origin main
+
+

可以把 main 换成你想要推送的任何分支,如master或者test

+

如果你的远程仓库是最新的,可以使用以下命令更新本地仓库:

+
git pull
+
+

合并分支

+

分支是用来将特性开发绝缘开来的。比如你在本地的test分支新增了一个功能,想要合并到主分支中。

+

创建一个叫做“test”的分支,并切换过去:

+
git checkout -b test
+
+

新增某些功能后切换回主分支:

+
git checkout master
+
+

在主分支上执行合并操作,将 test 分支的改动合并到主分支:

+
git merge test
+
+

推送完成后可以把新建的分支删掉:

+
git branch -d test
+
+

分支常用操作

+
- 列出所有本地分支
+git branch
+
+- 列出所有远程分支
+git branch -r
+
+- 列出所有本地分支和远程分支
+git branch -a
+
+- 列出所有本地分支,并展示没有分支最后一次提交的信息
+git branch -v
+
+- 列出所有本地分支,并展示没有分支最后一次提交的信息和远程分支的追踪情况
+git branch -vv
+
+- 列出所有已经合并到当前分支的分支
+git branch --merged
+
+- 列出所有还没有合并到当前分支的分支
+git branch --no-merged
+
+- 新建一个分支,但依然停留在当前分支
+git branch [branch-name]
+
+- 新建一个分支,并切换到该分支
+git checkout -b [branch]
+
+- 新建一个与远程分支同名的分支,并切换到该分支
+git checkout --track [branch-name]
+
+- 新建一个分支,指向指定commit
+git branch [branch] [commit]
+
+- 新建一个分支,与指定的远程分支建立追踪关系
+git branch --track [branch] [remote-branch]
+
+- 切换到指定分支,并更新工作区
+git checkout [branch-name]
+
+- 切换到上一个分支
+git checkout -
+
+- 建立追踪关系,在现有分支与指定的远程分支之间
+git branch --set-upstream-to=[remote-branch]
+git branch --set-upstream [branch] [remote-branch] - 已被弃用
+
+- 合并指定分支到当前分支
+git merge [branch]
+
+- 中断此次合并(你可能不想处理冲突)
+git merge --abort
+
+- 选择一个commit,合并进当前分支
+git cherry-pick [commit]
+
+- 删除分支
+git branch -d [branch-name]
+
+#新增远程分支 远程分支需先在本地创建,再进行推送
+git push origin [branch-name]
+
+- 删除远程分支
+git push origin --delete [branch-name]
+git branch -dr [remote/branch]
+
+

标签

+

Git 的 tag 功能主要用于给仓库历史中的某个特定提交打上“标签”,通常用于标记版本发布点(例如 v1.0、v2.0 等),以便于后续的版本定位、回溯和发布管理

+

标签类型

+

Git 提供两种类型的标签:

+
    +
  • +

    附注标签(Annotated Tag)会创建成一个完整的 Git 对象,存储打标签者的名字、邮箱、日期和标签说明,还可采用 GPG 进行签名。推荐用于正式发布,因为包含更多元数据和安全信息。

    +
  • +
  • +

    轻量标签(Lightweight Tag)实际上只是对某个提交的引用,不保存额外信息,类似一个固定的分支。适用于临时标记或非正式用途。

    +
  • +
+

创建标签

+
    +
  • 创建附注标签
  • +
+

使用 -a 参数表示“annotated”,并用 -m 提供标签说明。例如,给当前提交创建一个名为 v1.0 的附注标签:

+
git tag -a v1.0 -m "发布版本 v1.0"
+
+

这会在 Git 数据库中生成一个完整的标签对象,可通过 git show v1.0 查看标签信息和对应的提交详情。

+

如果需要给旧提交贴标签,可以在命令末尾指定提交的 SHA 值(部分 SHA 也可):

+
git tag -a v1.0 <commit-sha> -m "发布版本 v1.0"
+
+
    +
  • 创建轻量标签
  • +
+

直接指定标签名即可,不加任何参数:

+
git tag v1.0-light
+
+

轻量标签仅仅是一个提交引用,因此查看时不会显示附加信息。

+

列出标签

+
    +
  • 列出所有标签
  • +
+
git tag
+
+
    +
  • 还可以使用通配符过滤:
  • +
+
git tag -l "v1.*"
+
+

这样便于管理和筛选大量标签。

+
    +
  • 查看标签详细信息
  • +
+
git show v1.0
+
+

这会显示标签对象的元数据以及对应的提交记录。

+

推送标签

+

默认情况下,git push 不会将本地标签推送到远程仓库。推送标签有两种方式:

+
    +
  • 推送单个标签
  • +
+
git push origin v1.0
+
+
    +
  • 一次性推送所有标签
  • +
+
git push origin --tags
+
+

删除标签

+
    +
  • 删除本地标签
  • +
+
git tag -d v1.0
+
+
    +
  • 删除远程标签
  • +
+
git push origin --delete v1.0
+
+

日志

+

如果你想了解本地仓库的历史记录,最简单的命令就是使用:

+
git log
+
+
    +
  • 只看某一个人的提交记录:
  • +
+
git log --author=bob
+
+
    +
  • 一个压缩后的每一条提交记录只占一行的输出:
  • +
+
git log --pretty=oneline
+
+
    +
  • 看看哪些文件改变了:
  • +
+
git log --name-status
+
+

删除前一个提交记录

+

有时候手滑或者不想使用一个commit说明,可以用以下命令撤销上一个 commit:

+
git reset --soft HEAD~1
+
+

这个命令会撤销上一个 commit,但保留文件修改(代码仍然在工作区)。适用于 想要重新提交(amend)或调整 commit 的情况。

+

如果你想彻底删除更改(不保留代码修改),可以使用:

+
git reset --hard HEAD~1
+
+
+

注意:--hard 会清除未提交的更改,无法恢复。

+
+

.git 目录中主要文件和子目录的结构及其作用

+

📁 .git 目录结构概览

+
.git/
+├── HEAD
+├── config
+├── description
+├── hooks/
+├── index
+├── info/
+│   └── exclude
+├── logs/
+│   ├── HEAD
+│   └── refs/
+├── objects/
+│   ├── info/
+│   └── pack/
+├── refs/
+│   ├── heads/
+│   ├── remotes/
+│   └── tags/
+
+

🗂️ 核心文件和目录说明

+
    +
  • +

    HEAD:指向当前检出的分支或提交。例如,ref: refs/heads/main 表示当前位于 main 分支。

    +
  • +
  • +

    config:仓库级别的配置文件,包含用户名、邮箱、远程仓库等信息.

    +
  • +
  • +

    description:用于描述仓库,仅供 GitWeb 等工具使用。

    +
  • +
  • +

    hooks/:存放 Git 钩子脚本的目录,可用于在特定操作前后执行自定义脚本,如 pre-commitpost-merge 等.

    +
  • +
  • +

    index:暂存区(staging area)的索引文件,记录了即将提交的文件信息。

    +
  • +
  • +

    info/:包含辅助信息,如 exclude 文件用于定义仓库级别的忽略规则。

    +
  • +
  • +

    logs/:记录了引用(如分支、标签)的更新历史,有助于追踪操作记录。

    +
  • +
  • +

    objects/:存储 Git 的所有对象,包括:

    +
      +
    • blob:文件内容。
    • +
    • tree:目录结构。
    • +
    • commit:提交对象,记录提交信息和指向的树对象。
    • +
    • tag:标签对象。 +这些对象以 SHA-1 哈希命名,前两位作为子目录,其余作为文件名。
    • +
    +
  • +
  • +

    refs/:存储所有引用,包括:

    +
      +
    • heads/:本地分支。
    • +
    • remotes/:远程分支。
    • +
    • tags/:标签。
    • +
    +
  • +
+

Commit规范

+

提交信息的基本格式

+
    +
  • Header(头部) +格式:
  • +
+
<type>[可选的 scope]: <简短描述>
+
+

type 表示提交类型,如:feat(新功能)、fix(修复bug)等。 +scope 是可选的,用于指出变更影响的模块或范围。 +简短描述 用于概述本次提交的核心内容,通常使用祈使语气。

+
    +
  • +

    Body(正文) +用于详细说明变更的动机、方法以及可能的影响,建议每行不超过 72 个字符。

    +
  • +
  • +

    Footer(脚注) +可选部分,用来引用相关 issue、任务或说明破坏性变更(例如:BREAKING CHANGE: ...)。例如:

    +
  • +
+
Fixes #123
+
+

这可以在提交后自动关闭相关问题。

+

常见的 Commit 类型

+
- feat:新功能的添加
+    示例:feat(user): 添加用户注册功能
+
+- fix:修复 Bug
+    示例:fix(parser): 修复解析错误导致程序崩溃
+
+- docs:文档相关的修改
+    示例:docs(readme): 更新使用说明
+
+- style:代码格式、排版等不影响代码逻辑的调整
+    示例:style: 优化代码缩进和空格
+
+- refactor:代码重构,不涉及新功能或 Bug 修复
+    示例:refactor: 优化数据处理逻辑
+
+- perf:性能优化
+    示例:perf: 提升数据查询速度
+
+- test:添加或修改测试代码
+    示例:test: 补充用户登录单元测试
+
+- build:构建相关的变更,如依赖管理、构建脚本等
+    示例:build: 更新 webpack 配置
+
+- ci:持续集成相关的修改
+    示例:ci: 调整 GitHub Actions 配置
+
+- chore:其他杂项维护,不涉及源代码或测试文件的修改
+    示例:chore: 更新项目依赖
+
+- revert:回滚到上一个版本的提交
+    示例:revert: 撤销上次提交
+
+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-gpg/index.html b/public/about-gpg/index.html new file mode 100644 index 0000000..1a11ec9 --- /dev/null +++ b/public/about-gpg/index.html @@ -0,0 +1,281 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:GPG使用小记

+ + + + + + +
+

前言 PGP/GPG 的核心功能——公钥加密、数字签名、信任管理广泛用于各个行业,本文简单说明了其使用方法。

+

什么是 PGP 与 GPG

+
    +
  • +

    PGP(Pretty Good Privacy)

    +
      +
    • 由 Phil Zimmermann 于 1991 年发布,是第一个面向个人用户的大众化加密软件。
    • +
    • 采用公钥加密体系,用于对邮件和文件进行加密、签名与验证。
    • +
    +
  • +
  • +

    GPG(GNU Privacy Guard,又称 GnuPG)

    +
      +
    • 项目发起于 1997 年,由 Free Software Foundation 推动,是 GPL 许可的自由软件实现。
    • +
    • 完全兼容 OpenPGP 标准(RFC 4880),可无缝替代 PGP 软件。
    • +
    +
  • +
+

历史沿革

+ + + + + + + +
时间事件
1991 年Phil Zimmermann 发布 PGP 1.0,标志个人加密进入大众市场
1994 年PGP 因出口管制遭到美国政府调查,后续改版加密算法合规化
1997 年GNU 推出 GnuPG,目标创建一个开源、自由的 OpenPGP 实现
2001 年OpenPGP 正式成为 IETF 标准(RFC 2440)
2006 年GnuPG 2.0 发布,引入多子系统(gpg-agent、dirmngr 等)
2014 年OpenPGP 更新为 RFC 4880bis,GnuPG 不断改进对新算法的支持
+

核心作用

+ + + + + + + + + + + +
应用领域描述
1. 电子邮件加密与签名- PGP/MIME:通过邮件客户端(如 Thunderbird + Enigmail)对正文和附件加密,并用私钥签名。
- PGP inline:将加密/签名内容以纯文本形式嵌入邮件,兼容性更强。
2. 文件与目录的加密签名- 单文件加密/解密
gpg --encrypt --recipient Alice file.txt
gpg --decrypt file.txt.gpg
- 归档目录加密:使用 tar 打包后再加密。
- 签名校验
gpg --detach-sign --armor release.tar.gz
gpg --verify release.tar.gz.asc release.tar.gz
3. 软件包与系统镜像签名- Linux 包管理签名:APT、pacman-key 等验证来源可信性。
- 容器镜像签名:结合 TUF/Notary 使用 GPG 保护 Docker 镜像完整性。
4. SSH 公钥管理与登录- 将 GPG 子密钥作为 SSH 密钥使用:
echo "enable-ssh-support" >> ~/.gnupg/gpg-agent.conf
gpgconf --reload gpg-agent
ssh-add -L
- 好处:私钥集中管理、PIN保护、跨平台一致。
5. 自动化脚本与 CI/CD 环境- 用 GPG 自动签名构建产物,供用户验证。
- 将签名集成进发布脚本(如 release.sh),自动生成 .sig 并上传。
6. 文档与 PDF 数字签名- 利用 gpgsmOpenPGP.js 对 PDF、Office 文档签名,保障法律或审计合规性。
7. 密码管理与“密码库”- pass:每个密码为一个 GPG 加密文件,支持 Git 同步和版本控制。
- git-crypt:自动加密 Git 仓库中的敏感文件,仅授权者可解密。
8. 安全聊天与即时通讯- 将 OTR 会话密钥托管在 GPG 中(如 mcabber + OTR),实现端到端加密。
9. 时间戳与不可篡改日志- 结合 GPG 签名与时间戳协议(如 RFC 3161)验证文件/日志未被篡改。
10. 去中心化信任与身份管理- 使用 Web of Trust 模型构建可信身份网络,用于开源社区签名、Key Signing Party、LDAP 交换等。
+

安装 GnuPG

+
paru -S gnupg
+
+

生成公钥与私钥

+

使用如下命令:

+
gpg --full-generate-key
+
+

生成流程:

+
gpg (GnuPG) 2.4.7; Copyright (C) 2024 g10 Code GmbH
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+
+Please select what kind of key you want:
+   (1) RSA and RSA
+   (2) DSA and Elgamal
+   (3) DSA (sign only)
+   (4) RSA (sign only)
+   (9) ECC (sign and encrypt) *default*
+  (10) ECC (sign only)
+  (14) Existing key from card
+Your selection? 9   ## 默认选择ECC算法
+Please select which elliptic curve you want:
+   (1) Curve 25519 *default*
+   (4) NIST P-384
+   (6) Brainpool P-256
+Your selection? 1   ## 默认选择标准椭圆曲线
+Please specify how long the key should be valid.
+         0 = key does not expire
+      <n>  = key expires in n days
+      <n>w = key expires in n weeks
+      <n>m = key expires in n months
+      <n>y = key expires in n years
+Key is valid for? (0) 1y   ## 默认有效期为一年
+Key expires at 2026年06月17日 星期三 13时06分27秒 CST
+Is this correct? (y/N) y
+
+GnuPG needs to construct a user ID to identify your key.
+
+## 输入名字与邮箱,comment可省略
+
+Real name: xxx
+Email address: xxx@gmail.com
+Comment:
+You selected this USER-ID:
+    "xxx <xxx@gmail.com>"
+
+Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?
+Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
+We need to generate a lot of random bytes. It is a good idea to perform
+some other action (type on the keyboard, move the mouse, utilize the
+disks) during the prime generation; this gives the random number
+generator a better chance to gain enough entropy.
+We need to generate a lot of random bytes. It is a good idea to perform
+some other action (type on the keyboard, move the mouse, utilize the
+disks) during the prime generation; this gives the random number
+generator a better chance to gain enough entropy.
+
+

列出密钥

+
gpg --list-secret-keys --keyid-format long
+
+

其中sec ed25519/xxxxxxxxx 2025-06-17 [SC] [expires: 2026-06-17]的xxxxxxxxx即为公钥ID。

+

发布公钥

+

例如上传你的 key:

+
gpg --send-keys <你的Long‑Key‑ID>
+
+

默认为你的 gpg.conf 中配置的 keyserver,也可以显式指定:

+
gpg --keyserver hkps://keys.openpgp.org --send-keys <Key‑ID>
+
+

也可以使用如下命令导出公钥为可读 ASCII 格式,类似ssh-keys,随后即可发布在个人博客上等等。

+
gpg --armor --export <Key‑ID>  > mypubkey.asc
+
+

撤销公钥

+

如果怀疑密钥被泄露或被中间人替换,立即发布“撤销证书”(revocation certificate)并上传到 keyserver。

+
gpg --gen-revoke <KeyID> > revoke.asc
+
+

上传撤销证书后,所有人都能知道该公钥已不再可信。

+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-junk-cleanup/index.html b/public/about-junk-cleanup/index.html new file mode 100644 index 0000000..c1c9346 --- /dev/null +++ b/public/about-junk-cleanup/index.html @@ -0,0 +1,311 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:垃圾清理的艺术

+ + + + + + +
+

前言 在从前的机械硬盘时代,由于硬盘空间小,且没有时常清理垃圾文件,常常导致硬盘空间严重不足;特别是在以 Windows 平台为代表的 C/D盘 体系下。那么,我们常说的垃圾清理,释放硬盘空间,到底是在清理什么?哪些文件可以被清理?

+

垃圾清理

+

通常指的是清理计算机硬盘上的不必要或临时文件,以释放硬盘空间。这些文件包括:

+
    +
  1. 临时文件: 程序在运行时会生成临时文件,以帮助它们完成任务。这些文件在任务完成后不再需要,占据了硬盘空间,却没有被回收。
  2. +
  3. 缓存文件: 许多程序比如浏览器,会在本地存储缓存数据,以加快后续访问速度。但是,这些缓存文件可能会占据大量空间,尤其是在长时间不清理的情况下,这里点名国产的微信和QQ。
  4. +
+
+

注意,清理缓存文件可能意味着加载速度变慢或需要重新下载,耗费流量,视情况而清理。

+
+
    +
  1. 日志文件: 许多应用程序会生成日志文件来记录其活动和错误。这些日志文件可能会积累并占用大量空间,尤其是在长时间不清理的情况下。
  2. +
+
+

特别是C盘上的log文件,因为它们记录了系统和应用程序的运行情况,可能会变得相当庞大。因此,定期清理C盘中的log文件是维护系统性能和释放磁盘空间的重要步骤之一。

+
+
    +
  • 备份文件: 如果您的系统或软件定期创建备份或快照,旧版本备份可能会占用大量空间。您可以定期清理旧版本备份以释放空间。
  • +
  • 大型文件: 有些应用程序可能会生成大型临时数据文件,如媒体编辑软件的临时视频或音频文件。这些文件在任务完成后可能会被遗留,占据大量空间。
  • +
+
+

例如PS加载的工作文件,放C盘的话会占用大量空间。

+
+
    +
  1. 卸载残余: 在卸载应用程序时,有时候可能会留下一些残余文件,如配置文件、注册表项等,这些文件可能会继续占用硬盘空间,并且在一定程度上影响系统的性能。定期清理这些卸载残余是维护系统健康的一部分。
  2. +
+
+

还记得删除牛马软件时的挽留选项吗?里面往往藏着“保存个人配置”。

+
+
    +
  1. 重复文件: 在计算机系统中,有时候可能会出现重复的文件,这些文件可能是因为用户错误地复制或下载了多个副本,也可能是由于应用程序或系统错误导致文件重复。这些重复文件不仅占用了宝贵的存储空间,而且也增加了文件管理的复杂性。
  2. +
+
+

这里再次点名微信,同样一个文件能保存好几次,且不给出具体的存放路径,怪不得动辄十几个G,尾大不掉,真的离谱!

+
+
    +
  1. 回收站文件: 删除文件时,它们通常不会立即从硬盘上删除,而是移动到回收站。清空回收站可以释放这些被删除文件所占据的空间。
  2. +
+
+

注意,尽管清空回收站会立即释放硬盘空间,但实际上删除的文件并不会立即被擦除,而是被标记为可以被覆写的空间。在某些情况下,专业的数据恢复软件可能仍然可以找回部分被删除的文件。因此,如果希望永久删除文件而不被恢复,需要使用专门的文件删除工具,来覆盖文件内容以确保无法恢复。

+
+
    +
  1. 下载文件夹: 下载文件夹可能会积累大量临时文件、安装程序、文档和媒体文件。定期清理下载文件夹可以帮助释放硬盘空间。
  2. +
  3. 不再使用的程序: 有时候,安装的一些程序你已经不再使用或需要它们。卸载这些程序可以释放相关的硬盘空间。
  4. +
  5. 浏览器插件与扩展: 未使用的浏览器插件和扩展可能会占用不必要的资源和空间。删除不再需要的插件和扩展可以帮助优化浏览器性能并释放空间。
  6. +
  7. 安装程序和更新文件: 在安装程序或更新软件时,临时安装文件可能会留在系统中。这些文件通常可以安全删除,因为安装程序已经完成。
  8. +
+
+

例如安卓上的安装包(APK文件)和下载安装后的EXE文件。

+
+

需要注意的是,往往有许多牛马软件安装目录和文件目录不规范,或者是在安装时没有设定好,会产生大量垃圾文件;这时就需要垃圾清理工具或者手动遍历文件夹(注意隐藏文件夹)。

+

垃圾清理软件

+

Windows 平台:

+
    +
  1. WizTree WizTree是一款功能强大清理垃圾文件/在Windows上找到大文件以释放磁盘空间的首选程序...超级易于使用,快速闪电.
  2. +
  3. Disk Cleanup(磁盘清理): Windows 自带的磁盘清理工具,可以帮助您清理不必要的系统文件,包括临时文件、回收站等。
  4. +
  5. BleachBit BleachBit 是一款开源的系统清理工具,可以帮助您清理系统中的临时文件、缓存、浏览器历史等。
  6. +
+

macOS 平台:

+
    +
  1. CleanMyMac X: CleanMyMac X 是一款功能强大的系统优化工具,可以帮助您清理系统中的垃圾文件、优化性能,并提供了其他的实用工具。
  2. +
  3. Onyx: Onyx 是一款免费的 macOS 系统维护和优化工具,可以帮助您清理系统缓存、日志文件、临时文件等。
  4. +
  5. AppCleaner: AppCleaner 是一款简单易用的应用程序卸载工具,可以帮助您彻底清理 macOS 系统中的应用程序及其相关文件。
  6. +
+

Linux 平台:

+
    +
  1. BleachBit: BleachBit 不仅适用于 Windows,也提供了 Linux 版本,可以帮助您清理系统中的临时文件、缓存、浏览器历史等。
  2. +
  3. Stacer: Stacer 是一款开源的系统优化和监控工具,提供了垃圾清理、系统管理、系统监控等功能,适用于多种 Linux 发行版。
  4. +
  5. Sweeper(KDE 扫除者): Sweeper 是 KDE 桌面环境的一部分,提供了简单易用的垃圾清理功能,可以帮助您清理系统中的临时文件、缓存等。
  6. +
+

Arch linux 清理

+
    +
  1. +

    缓存清理:

    +
      +
    • sudo pacman -Sc: 清理包缓存,删除已安装的但不再需要的软件包。
    • +
    • sudo pacman -Scc: 进一步清理所有包文件,包括已下载的包。
    • +
    +
  2. +
  3. +

    系统日志:

    +
      +
    • /var/log 目录下包含系统日志文件。你可以删除较旧的日志文件,或者使用日志轮换工具,如 logrotate
    • +
    +
  4. +
  5. +

    临时文件:

    +
      +
    • /tmp 目录下包含临时文件。你可以通过 sudo rm -rf /tmp/* 清理它们。
    • +
    +
  6. +
  7. +

    缓存文件:

    +
      +
    • 一些应用程序会在 ~/.cache 目录下存储缓存文件。你可以检查该目录并删除不再需要的文件。
    • +
    +
  8. +
  9. +

    AUR 缓存:

    +
      +
    • AUR 辅助工具(如 yay)会在 ~/.cache/yay 目录下存储构建和下载的软件包。你可以清理这些文件。
    • +
    +
  10. +
  11. +

    旧内核:

    +
      +
    • 如果你安装了多个内核版本,你可以删除不再需要的旧内核。首先使用 uname -r 查看当前内核版本,然后使用 sudo pacman -Rns linux-older-kernel 删除不需要的版本。
    • +
    +
  12. +
  13. +

    不再使用的配置文件:

    +
      +
    • 检查家目录下的隐藏文件,如 ~/.config,并删除不再需要的配置文件。
    • +
    +
  14. +
  15. +

    Docker日志文件:
    +使用 docker ps -a 命令查找你感兴趣的容器的 ID。

    +
    docker ps -a
    +
    +

    进入容器的日志目录,路径类似于 /var/lib/docker/containers/<container-id>/

    +
    cd /var/lib/docker/containers/<container-id>/
    +
    +

    使用命令清理或删除日志文件。你可以删除所有日志文件,或者只删除特定的日志文件。

    +
    # 删除所有日志文件
    +rm *.log
    +
    +# 删除特定日志文件(例如 stdout 和 stderr)
    +rm *-json.log
    +
    +
  16. +
+

Arch Linux 安装备份

+

你可以定期备份 Arch Linux 安装的软件列表,以便在需要时轻松还原。

+
pacman -Qqe > package-list.txt
+
+

这将列出所有已安装的软件包,并将其保存到文件 package-list.txt 中。在还原系统时,你可以使用以下命令:

+
sudo pacman -S --needed - < package-list.txt
+
+

后记

+

垃圾文件的产生总是无可避免,这是因为随着使用时间的流逝,系统的熵值也在增大;生命以负熵为食,同样的为系统清理垃圾也是逆熵的一部分。在你的生命中会有许多电子设备,但它们往往只有你一任主人,请善待它们!

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-lazyvim/index.html b/public/about-lazyvim/index.html new file mode 100644 index 0000000..be41493 --- /dev/null +++ b/public/about-lazyvim/index.html @@ -0,0 +1,488 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:lazyvim快速上手

+ + + + + + +
+

前言 ​LazyVim 是一个基于 Neovim 的现代化配置框架,易于定制和扩展,这里对其介绍并说明使用方法。

+

Lazy!

+
+

LazyVim 是一个基于 Neovim 的现代化配置框架,旨在简化 Neovim 的配置过程。它通过集成的 lazy.nvim 插件管理器,提供了一种易于定制和扩展配置的方式,结合了从头开始配置的灵活性和预配置设置的便利性 。

+
+
+

LazyVim 是在Neovim的基础上进行配置,Neovim又继承了vim的操作模式,对vim不熟悉的同学可以看这里

+
+

安装

+

首先安装neovim,在arch linux上是:

+
paru -S neovim
+
+

在Ubuntu上是

+
sudo add-apt-repository ppa:neovim-ppa/unstable
+sudo apt update
+sudo apt install -y \ neovim git curl unzip build-essential ripgrep fd-find
+
+

备份现有配置:

+
mv ~/.config/nvim ~/.config/nvim.bak
+mv ~/.local/share/nvim ~/.local/share/nvim.bak
+
+

克隆 LazyVim Starter 模板:

+
git clone https://github.com/LazyVim/starter ~/.config/nvim
+
+

启动 Neovim:

+
nvim
+
+

首次启动时,LazyVim 会自动安装并配置所需的插件。

+

结构

+

LazyVim 的配置目录通常位于~/.config/nvim/中:

+
~/.config/nvim
+❯ tree
+.
+├── init.lua
+├── lazy-lock.json
+├── lazyvim.json
+├── LICENSE
+├── lua
+│   ├── config
+│   │   ├── autocmds.lua
+│   │   ├── keymaps.lua
+│   │   ├── lazy.lua
+│   │   └── options.lua
+│   └── plugins
+│       ├── example.lua
+│       └── mp.lua
+├── README.md
+└── stylua.toml
+
+4 directories, 12 files
+
+

另外在~/.local/share/nvim/lazy/LazyVim/lua/lazyvim/plugins/目录下看到的文件结构,是 LazyVim 为其核心插件和扩展插件提供的模块化配置体系。这些配置文件并不直接出现在~/.config/nvim/lua/plugins/目录中,是因为 LazyVim 采用了模块化和懒加载的设计理念,将核心插件和配置封装在其自身的代码库中。

+

各文件和目录的作用

+
    +
  • +

    init.lua:主配置文件,负责加载 lua/config/lazy.lua,从而引导整个 LazyVim 的初始化过程。

    +
  • +
  • +

    lazy-lock.json:由 lazy.nvim 插件管理器生成的锁定文件,记录了已安装插件的精确版本,确保插件的一致性。

    +
  • +
  • +

    lazyvim.json:用于记录通过 :LazyExtras 命令启用的额外功能(Extras),便于在不同设备间同步配置。

    +
  • +
  • +

    LICENSEREADME.md:分别为许可协议和项目说明文档。

    +
  • +
  • +

    stylua.tomlstylua 的配置文件,用于格式化 Lua 代码。

    +
  • +
  • +

    lua/config/:包含 Neovim 的基础配置文件,如自动命令(autocmds.lua)、快捷键(keymaps.lua)、插件管理(lazy.lua)和编辑器选项(options.lua)。这些文件会被 LazyVim 自动加载,无需手动引入。

    +
  • +
  • +

    lua/plugins/:用于添加或修改插件配置的目录。您可以在此目录中添加新的 Lua 文件,以引入其他插件或更改现有插件的设置。 +​

    +
  • +
+

Lazyvim自带配置

+

在 LazyVim 中,插件被分类为已加载(Loaded)和未加载(Not Loaded)。

+

✅ 已加载的插件(Loaded)

+
    +
  • +

    blink.cmp:一个高性能、开箱即用的自动补全引擎,旨在替代 nvim-cmp,提供更快的性能和更少的配置需求。

    +
  • +
  • +

    bufferline.nvim:用于在顶部显示缓冲区列表的插件,提供类似于浏览器标签页的界面。

    +
  • +
  • +

    friendly-snippets:一个包含多种语言代码片段的集合,可与多个片段引擎(如 luasnip)配合使用。

    +
  • +
  • +

    gitsigns.nvim:在编辑器中显示 Git 更改标记(如添加、修改、删除)的插件,增强版本控制的可视化。

    +
  • +
  • +

    lazy.nvim:LazyVim 的插件管理器,支持懒加载和依赖管理,提升启动速度和性能。

    +
  • +
  • +

    lualine.nvim:一个高度可定制的状态栏插件,支持多种主题和组件。

    +
  • +
  • +

    mason-lspconfig.nvim & mason.nvim:用于自动安装和配置 LSP(语言服务器协议)服务器的插件组合,简化开发环境的设置。

    +
  • +
  • +

    mini.aimini.pairsmini.nvim 插件集合的一部分,分别用于增强文本对象操作和自动括号配对功能。

    +
  • +
  • +

    noice.nvim:改进 Neovim 消息和命令行界面的插件,提供更丰富的 UI 体验。

    +
  • +
  • +

    nui.nvim:一个用于构建 Neovim 用户界面的 Lua 库,被多个插件作为依赖使用。

    +
  • +
  • +

    nvim-lint:一个异步代码检查器,支持多种语言的语法和风格检查。

    +
  • +
  • +

    nvim-lspconfig:提供预配置的 LSP 客户端设置,简化语言服务器的集成。

    +
  • +
  • +

    nvim-treesitternvim-treesitter-textobjectsnvim-ts-autotag:基于 Tree-sitter 的语法高亮和代码结构分析插件,增强代码编辑体验。

    +
  • +
  • +

    persistence.nvim:自动保存和恢复会话的插件,方便在不同项目之间切换。

    +
  • +
  • +

    snacks.nvim:提供快速导航和编辑功能的插件,提升编辑效率。

    +
  • +
  • +

    todo-comments.nvim:高亮和管理代码中的 TODO、FIXME 等注释的插件,方便任务跟踪。

    +
  • +
  • +

    tokyonight.nvim:一个流行的 Neovim 主题,提供多种配色方案。

    +
  • +
  • +

    trouble.nvim:一个用于显示诊断信息(如 LSP 错误、警告)的插件,提供统一的界面。

    +
  • +
  • +

    ts-comments.nvim:基于 Tree-sitter 的注释插件,支持多语言的智能注释功能。

    +
  • +
  • +

    which-key.nvim:在按下快捷键时弹出可用键位提示的插件,帮助记忆和发现快捷键。

    +
  • +
+

❌ 未加载的插件(Not Loaded)

+
    +
  • +

    catppuccin:一个柔和的 Neovim 主题,提供多种风格的配色方案。

    +
  • +
  • +

    conform.nvim:一个用于代码格式化的插件,支持多种语言的格式化工具。

    +
  • +
  • +

    grug-far.nvim:一个快速的全局查找和替换插件,提供直观的界面和操作。

    +
  • +
  • +

    lazydev.nvim:用于 LazyVim 插件开发的辅助工具,简化开发流程。

    +
  • +
  • +

    markdown-preview.nvim:在浏览器中实时预览 Markdown 文件的插件,提升写作体验。

    +
  • +
  • +

    plenary.nvim:一个 Lua 函数库,提供多种实用功能,被许多插件作为依赖使用。

    +
  • +
+

自定义配置

+
    +
  • +

    添加插件:​在 lua/plugins/ 目录下创建一个新的 Lua 文件,返回插件的配置表。

    +
  • +
  • +

    修改快捷键:​编辑 lua/config/keymaps.lua 文件,添加或修改快捷键映射。

    +
  • +
  • +

    调整选项:​编辑 lua/config/options.lua 文件,设置 Neovim 的行为选项。​

    +
  • +
+

常用快捷键

+

LazyVim 默认使用<space> 作为 <leader>,\ 作为<localleader>,并通过 which-key.nvim 插件动态展示所有以<space>开头的可用映射,极大降低了记忆成本。​

+
    +
  • 导航与窗口管理
  • +
+
- 在窗口间切换:Ctrl +h / Ctrl +j / Ctrl +k / Ctrl +l
+- 调整当前窗口尺寸:Ctrl + ↑ / Ctrl + ↓ / Ctrl + ← / Ctrl + →
+
+
    +
  • 缓冲区切换与管理
  • +
+
- 切换到上一个/下一个缓冲区:Shift +h / Shift +l
+- 切换“另一个”缓冲区:Space + b + b
+- 关闭当前缓冲区:Space + b + d
+- 只保留当前缓冲区:Space + b + o
+
+
    +
  • 文件与搜索
  • +
+
- 新建文件:Space + f + n
+- 打开文件(普通命令):输入 :e <文件名> 回车
+- 在项目根目录查找文件:Space + Space
+- 在项目根目录查找文件(另一路径):Space + f + f
+- 在当前工作目录查找文件:Space + f + F
+- 查找 Git 管理的文件:Space + f + g
+- 列出最近打开的文件:Space + f + r
+- 列出所有缓冲区:Space + ,
+- 全局全文搜索:Space + /
+
+
    +
  • 分割与终端
  • +
+
- 向下分割:Space + -
+- 向右分割:Space + |
+- 关闭当前窗口:Space + w + d
+- 窗口最大化/恢复:Space + w + m 或 Space + u + Z
+- 打开根目录终端:Space + f + t
+- 打开当前目录终端:Space + f + T
+- 切换(隐藏/显示)终端:Ctrl + /
+
+
    +
  • LSP 相关
  • +
+
- 跳转到定义:g + d
+- 查找引用:g + r
+- 跳转到实现:g + I
+- 跳转到声明:g + D
+- 查看文档悬停:K
+- 插入模式签名帮助:Ctrl + k
+- 代码操作:Space + c + a
+- 重命名:Space + c + r
+- 运行 CodeLens:Space + c + c
+- 显示行诊断:Space + c + d
+
+
    +
  • Git 操作
  • +
+
- 查看状态:Space + g + s
+- 查看差异:Space + g + d
+- 查看行级 Blame:Space + g + b
+- 在浏览器打开当前文件:Space + g + B
+- Git Stash(snacks.nvim):Space + g + S
+
+
    +
  • 诊断与快速修复
  • +
+
- 打开 Location List:Space + x + l
+- 打开 Quickfix List:Space + x + q
+- 在 Quickfix 跳转:[ q / ] q
+
+

添加插件

+
    +
  • Markdown预览
  • +
+

~/config/nvim/lua/plugins/下新建一个mp.lua,写入如下配置:

+
return {
+    {
+        "iamcco/markdown-preview.nvim",
+        cmd = { "MarkdownPreviewToggle", "MarkdownPreview", "MarkdownPreviewStop" },
+        ft = { "markdown" },
+        build = ':call mkdp#util#install()'
+    }
+}
+
+

随后即可在 Neovim 中打开一个 Markdown 文件,执行以下命令启动预览:​

+
:MarkdownPreview
+
+

tips

+
    +
  • lazyvim中的行号是非自然序的,这是为了方便光标移动而设置的:你可以在正常模式中通过10k快速移动光标到10行前,10j,10h,10l同理。
  • +
  • lazyvim的字体是和终端相同的,不同单独设置;
  • +
  • lazyvim中在侧边栏选择文件按d删除,按y复制,按p粘贴,按a创建,按r重命名;
  • +
  • gcc:注释当前行;
  • +
  • g+ctrl+g:显示信息;
  • +
  • alt+h:显示隐藏文件;
  • +
  • space+c+f:将当前代码格式化;
  • +
  • 设置文件编码:set fileencoding?
  • +
  • 设置换行符:set fileformat=unix
  • +
  • LSP快捷操作:
  • +
+ + + + + + + + +
快捷键功能
gd跳转到定义(Go to Definition)
gr查找引用(Go to References)
K显示悬浮文档(Hover)
<leader>rn重命名(Rename)
<leader>caCode Action(修复)
gl显示诊断信息(Diagnostic)
[d / ]d上/下一个诊断问题
+

Edit!

+
+

编辑器的基本素养

+
+

文件操作

+
    +
  • 创建文件/文件夹
  • +
  • 打开/关闭/切换文件
  • +
  • 复制/粘贴
  • +
  • 写入/保存/退出
  • +
  • 搜索替换
  • +
+

字符处理

+
    +
  • LF/CRLF处理
  • +
  • 零宽字符处理
  • +
  • GBK/UTF-8处理
  • +
+

终端

+
    +
  • 打开终端/复用终端
  • +
+

其他功能

+
    +
  • LSP
  • +
  • 代码调试
  • +
  • 工作区切换
  • +
  • Git支持
  • +
  • 主题与显示效果
  • +
+

🔗

+

用 neovim 写 markdown 是一种什么样的体验

+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-markdown/index.html b/public/about-markdown/index.html new file mode 100644 index 0000000..f0226ce --- /dev/null +++ b/public/about-markdown/index.html @@ -0,0 +1,402 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:Markdown使用快速教程

+ + + + + + +
+

前言 本文为 Markdown 教程,内容涵盖 Markdown 的历史、作用、基本语法和显示效果,可以在github将本文的源码拷贝供大家参考和学习。

+

Markdown 教程

+

零.常用的markdown编辑器

+ +

一、Markdown 简介

+

1.1 什么是 Markdown?

+

Markdown 是一种轻量级标记语言,最初由约翰·格鲁伯(John Gruber)在 2004 年创建,其设计目标在于简洁易读,同时能够快速转换为 HTML。Markdown 被广泛用于撰写文档、博客、论坛帖子以及 README 文档,其直观的语法和高度可读性受到开发者和写作者的一致好评。

+

1.2 Markdown 的历史和作用

+
    +
  • +

    历史沿革:
    +2004 年左右,随着互联网内容量的增加以及对纯文本格式的需求不断上升,人们开始寻找一种既能保留纯文本的可读性,又能方便地生成格式化内容(如 HTML)的解决方案。Markdown 应运而生。经过十多年的发展,Markdown 已衍生出多个方言(例如 GitHub Flavored Markdown、CommonMark 等),并被各种编辑器、静态博客生成器(如 Zola、Jekyll、Hugo 等)以及内容管理系统所支持。

    +
  • +
  • +

    主要作用:

    +
      +
    • 快速排版: Markdown 语法简单,使用自然语言符号来表示标题、列表、链接、图片等格式。
    • +
    • 跨平台兼容: 由于基于纯文本格式,Markdown 文件可以在任何文本编辑器中打开和编辑,而且可以很容易地转换成 HTML、PDF 等格式。
    • +
    • 降低学习成本: 与复杂的 HTML 标记相比,Markdown 的语法简单易懂,非常适合非程序员使用。
    • +
    • 促进内容创作: 许多博客平台和文档系统都采用 Markdown 作为主要写作格式,降低了内容创作和协作的门槛。
    • +
    +
  • +
+
+

二、Markdown 基本语法

+

下面详细介绍 Markdown 常用的语法,并演示其在渲染后显示的效果。

+

2.1 标题

+

使用井号 # 来表示标题,井号的数量表示标题级别(1~6级)。

+
# 这是一级标题
+## 这是二级标题
+### 这是三级标题
+#### 这是四级标题
+##### 这是五级标题
+###### 这是六级标题
+
+

渲染效果:

+

这是一级标题

+

这是二级标题

+

这是三级标题

+

这是四级标题

+
这是五级标题
+
这是六级标题
+
+

2.2 强调文本

+
    +
  • 斜体:在文字两侧加上一个星号 * 或下划线 _
  • +
  • 加粗:在文字两侧加上两个星号 ** 或下划线 __
  • +
  • 斜体加粗:在文字两侧加上三个星号 ***
  • +
+
*这是斜体*
+_这也是斜体_
+
+**这是加粗**
+__这也是加粗__
+
+***这是斜体加粗***
+
+

渲染效果:

+

这是斜体
+这也是斜体

+

这是加粗
+这也是加粗

+

这是斜体加粗

+
+

2.3 列表

+

无序列表

+

使用 -*+ 表示无序列表项。

+
- 项目 1
+- 项目 2
+  - 子项目 2.1
+  - 子项目 2.2
+- 项目 3
+
+

渲染效果:

+
    +
  • 项目 1
  • +
  • 项目 2 +
      +
    • 子项目 2.1
    • +
    • 子项目 2.2
    • +
    +
  • +
  • 项目 3
  • +
+

有序列表

+

使用数字后面跟点号来表示有序列表:

+
1. 第一项
+2. 第二项
+3. 第三项
+
+

渲染效果:

+
    +
  1. 第一项
  2. +
  3. 第二项
  4. +
  5. 第三项
  6. +
+
+

2.4 链接与图片

+

链接

+

格式:链接文字

+
[GitHub](https://github.com "GitHub 官网")
+
+

渲染效果:
+GitHub

+

图片

+

格式:![图片替代文本](图片 URL "可选标题")

+
![Markdown Logo](https://upload.wikimedia.org/wikipedia/commons/4/48/Markdown-mark.svg "Markdown")
+
+

渲染效果:

+

Markdown Logo

+
+

2.5 代码

+

行内代码

+

使用反引号 ` 来表示行内代码。

+
使用 `printf()` 函数输出内容。
+
+

渲染效果:
+使用 printf() 函数输出内容。

+

代码块

+

代码块使用三个反引号(```)包裹,也可以指定语言以便进行语法高亮。

+
```python
+def hello():
+    print("Hello, World!")
+```
+
+
+

注意:上述代码块中第一行的三个反引号后面紧跟着语言名称(如 python),结束时用相同的三个反引号结束。

+
+

渲染效果(依赖编辑器或平台的语法高亮支持):

+
def hello():
+    print("Hello, World!")
+
+
+

2.6 引用块

+

使用 > 来表示引用(Blockquote)。

+
> 这是引用的内容,可以用于引用名言或文章片段。
+> 
+> 多行引用时,每行前面都加上 `>`。
+
+

渲染效果:

+
+

这是引用的内容,可以用于引用名言或文章片段。

+

多行引用时,每行前面都加上 >

+
+
+

2.7 分割线

+

使用三个或更多的横线 ---、星号 *** 或下划线 ___ 来产生水平分割线。

+
---
+或者
+***
+或者
+___
+
+

渲染效果:

+
+

或者

+
+

或者

+
+
+

2.8 表格

+

Markdown 表格可以使用管道符 | 和短横线 - 来创建。

+
| 表头1 | 表头2 | 表头3 |
+| :---  | :---: | ---:  |
+| 左对齐 | 居中对齐 | 右对齐 |
+| 单元格内容 | 更多内容 | 数据 |
+
+

渲染效果:

+ + + +
表头1表头2表头3
左对齐居中对齐右对齐
单元格内容更多内容数据
+
+

注:
+“:---” 表示左对齐;
+“:---:” 表示居中对齐;
+“---:” 表示右对齐。

+
+
+

三、Markdown 高级语法与扩展

+

不同平台可能支持额外的 Markdown 扩展语法,下面列举一些常见的扩展功能:

+

3.1 脚注

+

某些 Markdown 方言支持脚注。脚注格式如下:

+
这是一个带脚注的句子.[^1]
+
+[^1]: 这是脚注的内容。
+
+

渲染效果:

+

这是一个带脚注的句子.1

+
1 +

这是脚注的内容。

+
+

3.2 任务列表

+

GitHub Flavored Markdown(GFM)支持任务列表,可以用于表示待办事项。

+
- [x] 完成 Markdown 教程
+- [ ] 阅读更多文章
+- [ ] 分享教程
+
+

渲染效果:

+
    +
  • +完成 Markdown 教程
  • +
  • +阅读更多文章
  • +
  • +分享教程
  • +
+
+

四、Markdown 使用注意事项

+
    +
  1. +

    空行与段落:
    +Markdown 使用一个或多个空行来分隔不同的段落。如果要换行但不创建新段落,在行尾添加两个或更多空格后回车即可。

    +
  2. +
  3. +

    转义字符:
    +如果想要显示 Markdown 特殊符号而不被解析,比如 *#\ 等,可以在前面加上反斜杠 \

    +
    \*这不是斜体,而是普通的星号\*
    +
    +

    渲染效果:
    +*这不是斜体,而是普通的星号*

    +
  4. +
  5. +

    原始文本展示:
    +为了展示 Markdown 源码而不被渲染,请使用代码块(反引号包围)或适用平台支持的原始文本标签(例如 {% raw %}{% endraw %})。

    +
  6. +
+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-mechrev-keyboard/index.html b/public/about-mechrev-keyboard/index.html new file mode 100644 index 0000000..f98de32 --- /dev/null +++ b/public/about-mechrev-keyboard/index.html @@ -0,0 +1,330 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:机械革命键盘失灵拯救记

+ + + + + + +
+

前言 机械革命作为一款极高性价比的笔记本,其优惠的力度和问题不断的故障让玩家们爱恨交织;作者在其上安装 Linux 时遇到了键盘失灵的问题,为了避免更多人踩坑,故写本文。

+

一.故障情况

+

作者在一台锐龙平台的笔记本上安装 Debian 时,先在虚拟机中尝试安装,没有发现异常;随后在实体机安装时发现 liveCD 中键盘不可用,无法设置密码和主机名,在连接外接键盘后安装完成,却发现Fn快捷键仍然可用。

+

二.具体思路

+

根据机革一贯的“特性”,作者猜测是因为 BIOS 或者 ACPI 出现了故障,随后在翻阅论坛时发现是由于锐龙笔记本键盘中断描述与其他键盘不同:其为边缘敏 感、低电平有效的;而蛟龙16K机器键盘实际是边缘敏感、高电平有效(Edge ActiveHigh)。结合 linux 的特性,读取到边缘敏感、低电平有效的中断时,会认为 BIOS 有Bug,会直接当成边缘敏感、高电平有效进行处理。因此,键盘就没有了响应。

+

三.解决方法

+

既然是高低电平表述的错误,那么我们只需建立DSDT 表副本,将其修改,然后让它优先启动,从而让键盘配置正常;另外还存在 BIOS 修复,内核编译的方法,比较复杂,这里不做说明。

+
首先建立一个DSDT文件夹:
+sudo su
+mkdir -p /home/dsdt
+
+随后将系统的DSDT表读取到里面,并安装acpica-tools:
+cat /sys/firmware/acpi/tables/DSDT > dsdt.dat
+apt install acpica-tools
+iasl -d dsdt.dat
+
+进入vim编辑DSDT表,没有vim的先安装一个:
+apt install vim
+vim dsdt.dsl
+
+搜索并替换 Device(PS2K) 下面的
+IRQ (Edge, ActiveLow, Shared, ) 
+为
+IRQ (Edge, ActiveHigh, Shared, ) 
+
+vim搜索的方法为在命令模式下按下“/”,键入搜索字符并回车即可,按“n”跳转到下一处,“N”跳转到前一处,按: wq保存:
+
+随后搜索DefinitionBlock,将其步进值增加一(十六进制),即更改
+DefinitionBlock ("", "DSDT", 2, "ALASKA", "A M I", 0x01072009)
+为
+DefinitionBlock ("", "DSDT", 2, "ALASKA", "A M I", 0x0107200A)
+
+关闭DSDT,并设置其优先启动
+iasl dsdt.dsl
+mkdir -p kernel/firmware/acpi
+cp dsdt.aml kernel/firmware/acpi/
+find kernel | cpio -H newc --create > acpi_override
+cp acpi_override /boot/acpi_override
+echo "GRUB_EARLY_INITRD_LINUX_CUSTOM=\"acpi_override\"" >>/etc/default/grub
+
+更新并重启:
+
+sudo grub-mkconfig -o /boot/grub/grub.cfg
+sudo grub-install /dev/sdX
+sudo grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=grub
+
+update-grub2
+reboot
+
+

不出意外,重启后键盘即可使用,若系统不同将 apt 替换即可。

+

四.其他问题

+

对于Redmi 或 Lenovo刚发布的AMD R7 6800H机型:

+
    +
  • WIFI没有驱动 - (螃蟹卡 8852be)。
  • +
  • 蓝牙没有驱动 - (螃蟹卡 8852be)。
  • +
  • 开启窗口特效后,kwin_x11进程CPU占用飙升。
  • +
  • 电源管理,无论怎么调,笔记本都发热很严重。
  • +
+

修复wifi驱动

+
# 内核小于5.18的
+git clone https://github.com/HRex39/rtl8852be.git
+# 内核大于等于5.18的
+git clone https://github.com/HRex39/rtl8852be.git -b dev
+
+cd rtl8852be
+make -j8
+sudo make install
+sudo modprobe 8852be
+
+

修复蓝牙驱动

+
# 内核=5.15
+git clone https://github.com/HRex39/rtl8852be_bt.git -b 5.15
+# 内核=5.18
+git clone https://github.com/HRex39/rtl8852be_bt.git -b 5.18
+
+cd rtl8852be_bt
+make -j8
+sudo make install
+
+

修复kwin_x11显卡未驱动

+

首先去amd官网下载最新的linux-amd驱动:

+
https://www.amd.com/zh-hans/support/linux-drivers // 22.20 for Ubuntu 20.04.5 HWE
+
+

修改Deepin为ubuntu

+
sudo vim /etc/os-release // ID=Deepin => ID=ubuntu
+
+sudo apt install ./amdgpu-install_22.20.50200-1_all.deb
+
+sudo vim /etc/apt/sources.list.d/amdgpu.list // focal => bionic
+
+sudo apt update
+
+sudo amdgpu-install --no-dkms
+
+sudo apt install inxi clinfo
+
+

安装成功以后,用inxi查看下:

+

inxi -G

+
Graphics:  Device-1: AMD Rembrandt driver: amdgpu v: kernel 
+           Display: x11 server: X.Org 1.20.11 driver: amdgpu,ati unloaded: fbdev,modesetting,vesa 
+           resolution: 1920x1080~60Hz 
+           OpenGL: renderer: AMD YELLOW_CARP (LLVM 14.0.1 DRM 3.42 5.15.34-amd64-desktop) 
+           v: 4.6 Mesa 22.1.0-devel
+
+

最后还原最初的修改:

+
sudo vim /etc/os-release // ID=ubuntu => ID=Deepin
+sudo apt purge amdgpu-install
+
+

看下效果图:

+
➜  ~ glxinfo -B
+name of display: :0
+display: :0  screen: 0
+direct rendering: Yes
+Extended renderer info (GLX_MESA_query_renderer):
+    Vendor: AMD (0x1002)
+    Device: AMD YELLOW_CARP (LLVM 14.0.1, DRM 3.42, 5.15.34-amd64-desktop) (0x1681)
+    Version: 22.1.0
+    Accelerated: yes
+    Video memory: 2048MB
+    Unified memory: no
+    Preferred profile: core (0x1)
+    Max core profile version: 4.6
+    Max compat profile version: 4.6
+    Max GLES1 profile version: 1.1
+    Max GLES[23] profile version: 3.2
+Memory info (GL_ATI_meminfo):
+    VBO free memory - total: 1388 MB, largest block: 1388 MB
+    VBO free aux. memory - total: 3047 MB, largest block: 3047 MB
+    Texture free memory - total: 1388 MB, largest block: 1388 MB
+    Texture free aux. memory - total: 3047 MB, largest block: 3047 MB
+    Renderbuffer free memory - total: 1388 MB, largest block: 1388 MB
+    Renderbuffer free aux. memory - total: 3047 MB, largest block: 3047 MB
+Memory info (GL_NVX_gpu_memory_info):
+    Dedicated video memory: 2048 MB
+    Total available memory: 5120 MB
+    Currently available dedicated video memory: 1388 MB
+OpenGL vendor string: AMD
+OpenGL renderer string: AMD YELLOW_CARP (LLVM 14.0.1, DRM 3.42, 5.15.34-amd64-desktop)
+OpenGL core profile version string: 4.6 (Core Profile) Mesa 22.1.0-devel
+OpenGL core profile shading language version string: 4.60
+OpenGL core profile context flags: (none)
+OpenGL core profile profile mask: core profile
+
+OpenGL version string: 4.6 (Compatibility Profile) Mesa 22.1.0-devel
+OpenGL shading language version string: 4.60
+OpenGL context flags: (none)
+OpenGL profile mask: compatibility profile
+
+OpenGL ES profile version string: OpenGL ES 3.2 Mesa 22.1.0-devel
+OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
+
+

手动管理电源,避免CPU过度使用而发热

+

安装下面的三方电源管理工具 Boost Changer,选择 Performance策略即可

+
wget https://github.com/nbebaw/boostchanger/releases/download/v4.4.0/boostchanger_4.4.0_amd64.deb
+
+

参考

+

https://zhuanlan.zhihu.com/p/530643928

+

https://github.com/HRex39/rtl8852be

+

https://github.com/HRex39/rtl8852be_bt

+

https://bbs.deepin.org/post/241607

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-opensource/index.html b/public/about-opensource/index.html new file mode 100644 index 0000000..bdbd299 --- /dev/null +++ b/public/about-opensource/index.html @@ -0,0 +1,299 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:开源软件与协议

+ + + + + + +
+

前言 本文旨在介绍开源以及开源许可证,这些许可证规定了使用、修改和分发开源软件的条件。通过了解不同类型的开源许可证及其特点,读者将能够更好地理解在开发和使用开源软件时的法律和道德责任。

+

开源的概念

+

「开源」一词对应英文 Open Source,最初起源于软件开发领域,因此也称为「开放源代码」,对应的软件则称为开源软件(Open Source Software,简称 OSS)。除了我们熟知的开源软件以外,开源的表现形式还有很多,例如开源硬件(Open Source Hardware)、开放设计(Open Design)、开放文档(Open Document)等等。开源的目的是分享共享、加速创新,可以说开源已经成为一种超越软件生产界限的运动和工作方式。

+

对于很多刚踏入软件这个行业的小伙伴来说,「开源」是个比较陌生的概念。但是随着经手项目逐渐增多,会发现很多项目,尤其是一些大型项目,经常会引用到别人一些优秀的开源代码,而这些优秀的开源代码通常都会在最开始简单地附上一段关于授权的声明或在项目根目录下提供完整的授权声明文件,比如:「The project is licensed under the Apache 2 license.」,诸如此类便是「开源许可证」。

+

开源不等于免费,开源也不等于没有约束

+

开源的好处

+
    +
  1. +

    透明度和安全性 +开源软件的代码是公开的,任何人都可以检查和改进它。这使得潜在的安全漏洞更容易被发现和修复,提升了软件的安全性。

    +
  2. +
  3. +

    促进创新 +开源允许开发者自由研究和修改代码,推动技术进步。例如,Linux、Python、TensorFlow 等开源项目极大地促进了计算机科学和人工智能的发展。

    +
  4. +
  5. +

    降低成本 +企业和个人可以免费使用开源软件,而不需要支付高昂的许可证费用。例如,使用 Linux 服务器代替 Windows Server 可以减少 IT 成本。

    +
  6. +
  7. +

    快速迭代和社区支持 +开源项目通常由全球开发者社区维护和改进,Bug 修复和新功能开发的速度比封闭源代码的软件更快。例如,开源浏览器 Firefox 就依赖社区贡献不断改进。

    +
  8. +
  9. +

    避免供应商锁定 +开源软件允许用户自由选择和修改代码,而不是被某个公司的专有软件绑定,避免了供应商锁定的问题。例如,MySQL 和 PostgreSQL 等开源数据库是很多企业的首选,避免依赖单一厂商。

    +
  10. +
+

开源软件

+

开源软件,顾名思义是指能够免费且不受限制地使用、再开发、再发布的软件。但在狭义上,只有符合开放源代码促进会(Open Source Initiative)定义的软件才能被称为开源软件。这个定义提出了十个特征,必须全部符合才能认定为开源软件。

+

这些特征包括:

+
    +
  • 可自由再分发。
  • +
  • 提供源代码。
  • +
  • 允许衍生作品。
  • +
  • 不得过度限制原始代码的修改。
  • +
  • 不得歧视特定人、群体或用途。
  • +
  • 必须「技术中立」等。
  • +
+

根据这些标准,一些看似自由使用的软件可能不符合开源软件的定义。例如,Elasticsearch原本使用Apache 2.0授权,是真正的开源软件。但面对云服务提供商如AWS等将其用于营利目的却不回馈改进的情况,Elasticsearch在2021年1月选择了SSPL(Server Side Public License,服务器端公共许可证)和Elastic License两种许可证并行;SSPL要求如果将程序的功能或修改后的版本作为服务提供给第三方,则必须免费公开提供服务源代码,这违背了开源软件的定义。另一方面,Elastic License要求不能向第三方提供主机或托管服务,也违反了开源软件的定义,因此也不算严格意义上的「开源」。

+

开源许可证

+

开源许可证是软件许可证的一种特殊形式,用于规定开源软件的使用、修改、分享等相关事宜。它是一种格式合同,涉及版权、专利、商标等权利义务,自动生效。

+

在美国,一些法院认为软件许可证是合同(contract),一些法院则认为是许可(license)。两者的区别在于,许可在传统上是由地产或物主作出的,目的在于允许他人使用自己的地块或物品。因此,它是单方向的,不构成完整的合同,而是作为合同的一个要素,用来和他人交换的条件。由于合同和许可之分在法律上有着重要的意义,它们的违约救济和版权侵权救济等方面有着不同的规定。

+

与美国不同,大陆法系国家如中国普遍认为开源软件许可证构成合同,但这种合同是事先规定好的标准化格式合同,并且自动生效。

+

开源许可证的种类繁多,据不完全统计,广义上的开源许可证超过200种,其中OSI批准的许可证有96个。这些许可证的内容各不相同,有些条款非常有意思,例如,啤酒软件许可证(Beerware License)规定,用户与作者聚会时可以请作者喝一杯啤酒;Jason Hunter 许可证规定,如果将该许可证下的代码用于商业目的,那么项目开发团队的所有成员都必须拥有 Jason Hunter 撰写的《Java Servlet编程》最新版。

+

常见开源许可证

+

世界上的开源许可证(Open Source License)大概有上百种,而常见的开源协议大致有GPL、BSD、MIT、Mozilla、Apache和LGPL等。 +alt text

+
+

Choose an open source license

+
+

Apache License

+

Apache License(Apache许可证),是Apache软件基金会发布的一个自由软件许可证。

+

Apache Licence 是著名的非盈利开源组织 Apache 采用的协议。该协议和BSD类似,同样鼓励代码共享和最终原作者的著作权,同样允许源代码修改和再发布。但是也需要遵循以下条件:

+
    +
  • 需要给代码的用户一份 Apache Licence。
  • +
  • 如果修改了代码,需要再被修改的文件中说明。
  • +
  • 在衍生的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明。
  • +
  • 如果再发布的产品中包含一个 Notice 文件,则在Notice文件中需要带有 Apache Licence。你可以在 Notice 中增加自己的许可,但是不可以表现为对 Apache Licence 构成更改。
  • +
+

Apache Licence 也是对商业应用友好的许可。使用者也可以再需要的时候修改代码来满足并作为开源或商业产品发布/销售。

+

使用这个协议的好处是:

+
    +
  • 永久权利 一旦被授权,永久拥有。
  • +
  • 全球范围的权利 在一个国家获得授权,适用于所有国家。假如你在美国,许可是从印度授权的,也没有问题。
  • +
  • 授权免费 无版税, 前期、后期均无任何费用。
  • +
  • 授权无排他性 任何人都可以获得授权
  • +
  • 授权不可撤消 一旦获得授权,没有任何人可以取消。比如,你基于该产品代码开发了衍生产品,你不用担心会在某一天被禁止使用该代码
  • +
+

BSD

+

BSD 是"Berkeley Software Distribution"的缩写,意思是"伯克利软件发行版"。

+

BSD开源协议:是一个给于使用者很大自由的协议。可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。 当你发布使用了BSD协议的代码,或则以BSD协议代码为基础做二次开发自己的产品时,需要满足三个条件:

+
    +
  • +

    如果再发布的产品中包含源代码,则在源代码中必须带有原来代码中的BSD协议。

    +
  • +
  • +

    如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议。

    +
  • +
  • +

    不可以用开源代码的作者/机构名字和原来产品的名字做市场推广。

    +
  • +
+

BSD代码鼓励代码共享,但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上开发商业软件发布和销售,因此是对商业集成很友好的协议。而很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者二次开发。

+

GPL

+

GPL (GNU General Public License) :GNU通用公共许可协议。

+

Linux 采用了 GPL。

+

GPL 协议和 BSD, Apache Licence 等鼓励代码重用的许可很不一样。GPL 的出发点是代码的开源/免费使用和引用/修改/衍生代码的开源/免费使用,但不允许修改后和衍生的代码做为闭源的商业软件发布和销售。这也就是为什么我们能用免费的各种 linux,包括商业公司的 linux 和 linux 上各种各样的由个人,组织,以及商业软件公司开发的免费软件了。

+

LGPL

+

LGPL是GPL的一个为主要为类库使用设计的开源协议。和 GPL 要求任何使用/修改/衍生之GPL类库的的软件必须采用GPL协议不同。LGPL允许商业软件通过类库引用(link)方式使用LGPL类库而不需要开源商业软件的代码。这使得采用 LGPL 协议的开源代码可以被商业软件作为类库引用并发布和销售。

+

但是如果修改 LGPL 协议的代码或者衍生,则所有修改的代码,涉及修改部分的额外代码和衍生的代码都必须采用 LGPL 协议。因此LGPL协议的开源代码很适合作为第三方类库被商业软件引用,但不适合希望以 LGPL 协议代码为基础,通过修改和衍生的方式做二次开发的商业软件采用。

+

GPL/LGPL都保障原作者的知识产权,避免有人利用开源代码复制并开发类似的产品。

+

MIT

+

MIT是和BSD一样宽范的许可协议,源自麻省理工学院(Massachusetts Institute of Technology, MIT),又称X11协议。作者只想保留版权,而无任何其他了限制。MIT与BSD 类似,但是比 BSD 协议更加宽松,是目前最少限制的协议。这个协议唯一的条件就是在修改后的代码或者发行包包含原作者的许可信息。适用商业软件。使用MIT的软件项目有:jquery、Node.js。

+

MIT与BSD类似,但是比BSD协议更加宽松,是目前最少限制的协议。这个协议唯一的条件就是在修改后的代码或者发行包包含原作者的许可信息。适用商业软件。使用MIT的软件项目有:jquery、Node.js。

+

MPL (Mozilla Public License 1.1)

+

MPL 协议允许免费重发布、免费修改,但要求修改后的代码版权归软件的发起者 。这种授权维护了商业软件的利益,它要求基于这种软件的修改无偿贡献版权给该软件。这样,围绕该软件的所有代码的版权都集中在发起开发人的手中。但MPL是允许修改,无偿使用得。MPL 软件对链接没有要求。

+

EPL (Eclipse Public License 1.0)

+

EPL允许 Recipients 任意使用、复制、分发、传播、展示、修改以及改后闭源的二次商业发布。

+

使用EPL协议,需要遵守以下规则:

+

当一个 Contributors 将源码的整体或部分再次开源发布的时候,必须继续遵循EPL开源协议来发布,而不能改用其他协议发布.除非你得到了原"源码"Owner 的授权;

+

EPL协议下,你可以将源码不做任何修改来商业发布.但如果你要发布修改后的源码,或者当你再发布的是 Object Code 的时候,你必须声明它的 Source Code 是可以获取的,而且要告知获取方法;

+

当你需要将EPL下的源码作为一部分跟其他私有的源码混和着成为一个 Project 发布的时候,你可以将整个 Project/Product 以私人的协议发布,但要声明哪一部分代码是EPL下的,而且声明那部分代码继续遵循EPL;

+

4.独立的模块(Separate Module),不需要开源。

+

Creative Commons 知识共享协议

+

Creative Commons (CC) 许可协议并不能说是真正的开源协议,它们大多是被使用于设计类的工程上。 CC 协议种类繁多,每一种都授权特定的权利。 一个 CC 许可协议具有四个基本部分,这几个部分可以单独起作用,也可以组合起来。下面是这几部分的简介:

+
    +
  • +

    署名 作品上必须附有作品的归属。如此之后,作品可以被修改,分发,复制和其它用途。

    +
  • +
  • +

    相同方式共享 作品可以被修改、分发或其它操作,但所有的衍生品都要置于CC许可协议下。

    +
  • +
  • +

    非商业用途 作品可以被修改、分发等等,但不能用于商业目的。但语言上对什么是"商业"的说明十分含糊不清 (没有提供精确的定义),所以你可以在你的工程里对其进行说明。例如,有些人简单的解释"非商业"为不能出售这个作品。而另外一些人认为你甚至不能在有广告的网站上使用它们。 还有些人认为"商业"仅仅指你用它获取利益。

    +
  • +
  • +

    禁止衍生作品

    +
  • +
+

CC 许可协议的这些条款可以自由组合使用。大多数的比较严格的CC协议会声明 "署名权,非商业用途,禁止衍生"条款,这意味着你可以自由的分享这个作品,但你不能改变它和对其收费,而且必须声明作品的归属。这个许可协议非常的有用,它可以让你的作品传播出去,但又可以对作品的使用保留部分或完全的控制。最少限制的CC协议类型当属 "署名"协议,这意味着只要人们能维护你的名誉,他们对你的作品怎么使用都行。

+

CC 许可协议更多的是在设计类工程中使用,而不是开发类,但没有人或妨碍你将之使用与后者。只是你必须要清楚各部分条款能覆盖到的和不能覆盖到的权利。

+

参考

+ + +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-podcast-use/index.html b/public/about-podcast-use/index.html new file mode 100644 index 0000000..bd7d3af --- /dev/null +++ b/public/about-podcast-use/index.html @@ -0,0 +1,210 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

搭建个人信息流:播客收听指北

+ + + + + + +
+

前言 讲起播客,许多人第一反应是喜马拉雅,但其实播客的订阅和收听有许多种方式。本文带你了解订阅播客的各种方式,并告诉你市面上有哪些不错的播客客户端可供选择。

+

一.什么是播客

+

播客是一种通过互联网传播音频或视频文件的媒体形式。这个词汇是由“广播”(broadcasting)和“iPod”(一种流行的便携式媒体播放器)两个词组合而成的。播客通常是由个人、组织或公司制作,并通过互联网上的订阅服务分享给观众。

+
    +
  • +

    定期更新: 播客通常以系列形式发布,每一集都是一个独立的音频或视频文件。制作者会定期发布新的内容,让观众订阅后能够定期收听或观看。

    +
  • +
  • +

    订阅:观众可以通过订阅播客来自动获取最新的内容。这意味着一旦订阅了某个播客,新的内容就会自动下载到用户的设备上,方便随时收听或观看。

    +
  • +
  • +

    多样的内容: 播客内容非常多样化,涵盖了几乎所有可能的主题,包括新闻、科技、文化、教育、娱乐等。从个人讲述生活故事到专业领域的讨论,播客的形式和内容都非常灵活。

    +
  • +
  • +

    低门槛制作:制作播客相对来说不需要太多的专业设备和技能,因此许多个人或小团队可以轻松开始制作自己的播客。

    +
  • +
+

播客的流行得益于它提供了一种轻松、灵活、个性化的信息传递方式,让人们可以方便地在各种主题上深入了解或娱乐。

+

二.如何听播客

+

要收听播客,首先得确定自己所用的平台和客户端,一般有以下几种:

+
    +
  • +

    使用播客应用: 最常见的方式是使用专门的播客应用程序,这些应用可以在智能手机、平板电脑或计算机上安装。一些常见的播客应用包括 Apple Podcasts(苹果播客)、Spotify、Google Podcasts(谷歌播客)、Pocket Casts等。这些应用通常允许你搜索、订阅和播放播客。像喜马拉雅以及各大云音乐等非泛用型播客客户端,这类软件的特点是收听方便,种类繁多,但一般不开源,也没有 RSS 链接。

    +
  • +
  • +

    在网页上收听: 许多播客也提供在其官方网站上在线收听的选项。你可以在制作者的网站上找到相应的播客链接,然后直接在浏览器中收听,或者使用浏览器插件。

    +
  • +
  • +

    通过流媒体服务: 一些流媒体服务,如 Spotify、Apple Music 等,也提供了播客的功能。你可以在这些服务中搜索并订阅你感兴趣的播客。

    +
  • +
  • +

    通过RSS订阅: 几乎每个独立播客的主播都会反复强调「请使用节目 RSS 链接在 泛用型播客客户端 里订阅节目」,一定程度上有无 RSS 订阅链接是作为独立播客的判断标准。使用 RSS 链接订阅播客其实非常简单——得到节目的 RSS 订阅链接后,将之粘贴到你的播客客户端内(通常是节目的搜索栏或地址栏)即可。大多数播客应用都支持这种方式。注意,例如喜马拉雅、荔枝等平台是没有原生RSS链接的,因此,对第三方服务生成的 RSS 链接要注意鉴别。有些服务提供者会在不告知主播和听众的前提下,私自在节目中间插入广告,非常影响节目收听体验,在使用时请注意甄别。

    +
  • +
+

三.常见客户端优缺点

+

我个人推荐使用开源的 AntennaPod 。

+

四.播客资源

+

天仙子的播客年度总结:播客选录

+

中文播客榜

+

Podcast search

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-rss-read/index.html b/public/about-rss-read/index.html new file mode 100644 index 0000000..a8fa799 --- /dev/null +++ b/public/about-rss-read/index.html @@ -0,0 +1,379 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

搭建个人信息流:RSS阅读指南

+ + + + + + +
+

前言 RSS 提供了一种数据格式,以 XML(可扩展标记语言)的形式组织信息,包括文章标题、摘要、链接和发布日期等。这些信息形成了所谓的“订阅源”(Feed),用户可以使用RSS阅读器(Feed Reader)来订阅这些源。

+

一.什么是RSS

+

如果你使用过类似红板报,轻芒杂志,摸鱼 kiki,今日热榜等 APP,应该对 RSS 并不陌生。

+

RSS(Really Simple Syndication)是一种用于发布经常更新的内容的标准,通常用于博客、新闻网站和其他线上发布的信息。RSS 允许用户订阅这些站点的内容,以便在内容有更新时,用户能够获得及时的通知。

+

基本上,RSS 提供了一种数据格式,以 XML(可扩展标记语言)的形式组织信息,包括文章标题、摘要、链接和发布日期等。这些信息形成了所谓的“订阅源”(Feed),用户可以使用 RSS 阅读器(Feed Reader)来订阅这些源。

+

RSS 的主要优势包括:

+
    +
  • +

    即时通知:用户订阅了 RSS 源后,当源中的内容有更新时,用户将立即收到通知,而无需手动检查网站。

    +
  • +
  • +

    集中管理:使用 RSS 阅读器,用户可以集中管理多个网站的更新,而无需逐个访问这些站点。

    +
  • +
  • +

    隐私保护:RSS 订阅不需要提供个人信息,用户只需关注感兴趣的内容,而无需注册账户。

    +
  • +
  • +

    定制内容:用户可以选择订阅感兴趣的主题或网站,定制他们的信息流。

    +
  • +
  • +

    减少信息过载:通过只关注真正感兴趣的内容,用户可以减少信息过载,集中注意力在最关键的信息上。

    +
  • +
+

如果我们想更高效地获取信息,不在多个应用间来回切换,另一方面拒绝算法给我们推荐的内容,那么建议用回原始的 RSS。

+

虽然 RSS 曾经非常流行,但随着社交媒体和其他信息传递方式的兴起,逐渐成为时代的眼泪。然而,RSS 仍然是一种有效的信息分发和获取方式,许多网站和博客仍提供 RSS 源。题主曾经计划使用 Kindle 作为专门的RSS阅读器,后来由于过于昂贵而作罢。

+

二.如何进行RSS阅读

+

基本上有以下几步:

+
    +
  • +

    寻找 RSS 订阅源

    +
  • +
  • +

    确定 RSS 客户端

    +
  • +
  • +

    自建 RSS 服务端(可选)

    +
  • +
+

寻找RSS订阅源

+

要知道一个网站是否支持 RSS 订阅,最直接的方法就是看网站的底部或侧边栏是否有 RSS 图标。一般来说,图标所指向的地址就是该网站的订阅链接,可以直接点击 跳转到 RSS 客户端内进行订阅,也可以复制粘贴按钮中的地址到自己在用的 RSS 服务中订阅这些网站中的内容。

+

在浏览器中推荐使用 RSS Hub radar 插件,可以自动找到可用的RSS源并提示。

+

有时候网站不会直接给出订阅源,这时候你也可以尝试在网站域名后面加上 /feed 或 /rss 或许可以碰巧猜中,比如少数派的 RSS 订阅链接就是 https://sspai.com/feed。当然,你也可以直接通过搜索引擎通过 网站名 + RSS 的关键字进行搜索,往往都能找到支持网站的 RSS 链接。

+

MoreRSS,这个网站提供中、英文的RSS源,并且显示源的订阅量,对于一些受欢迎的英文 RSS,还提供了中文翻译。但此网站还在建设中,收录量不大、功能也不完善,可以关注其更新。

+

有一些中文博客聚合网站,收录了多则1000+少则几百的中文博客(PS.经查世界上现存的大熊猫数量约2600只),知名的有十年之约、博友圈、BlogFinder 、积薪、川流 等,不一一列举了。

+

Feedsearch,如果在网站的首页看不到 RSS 信息,可以使用这个 RSS 源搜索服务,实测准确度很高,我用它找出来很多隐藏的 RSS 源,如果这个网站搜不到,那可能是网站确实没有提供 RSS。

+

RSSAnything ,如果 RSSHub 也没有找到需要的 RSS,可以尝试使用这个网站生成 RSS,这是我试过的效果最好的,但要看运气,有的时候效果很好,有的时候达不到期望值。

+

有一些针对具体的社会化媒体生成 RSS 的服务,但或者收费,或者稳定性欠佳失效,或者收费且稳定性欠佳失效(我就订阅了一个微信公众号的 RSS 服务,没用多久就失效了还不退款),想了下,就不在这里列举了,感兴趣可以直接在https://morerss.com/tools_zh.html查找。

+
+

英文RSS源翻译
+可以把外语信息源翻译为中文的,这里推荐的服务器是 RSS-Translator,功能强大但需要一定的能力。MoreRSS 基于 RSS-Translator 的服务,翻译了一批优质的外语信息源,可以直接订阅。

+
+

当然,我们也可以直接导入现有的订阅源,一般为 OPML 文件,如 RSS Source;或者调用第三方的 RSS 服务,如 anyfeeder,等等。

+

这里介绍一个 RSS 神器,由 DIygod 发起的RSShub项目:

+

RSSHub 是一个开源项目,旨在为用户提供一个集中化、可定制的RSS(Really Simple Syndication)源的生成器。该项目的目标是通过从各种网站和平台获取信息,将其聚合到用户自定义的RSS源中,从而使用户能够方便地订阅他们关心的内容。

+
    +
  • +

    开源性质: RSSHub 是一个开源项目,其源代码可以在 GitHub 上找到。这意味着任何人都可以查看、使用、修改和贡献代码。

    +
  • +
  • +

    支持的站点: RSSHub 支持从各种网站和平台提取数据,包括但不限于新闻网站、社交媒体、博客、视频分享平台等。用户可以根据自己的需求选择要订阅的站点。

    +
  • +
  • +

    自定义生成: 用户可以通过指定参数和规则来定制他们的 RSS 源,以便获取特定主题或关键字的更新。这使得用户能够灵活地定制他们的订阅流。

    +
  • +
  • +

    社区参与: RSSHub 是一个社区驱动的项目,有很多开发者和贡献者参与其中。社区可以通过 GitHub 进行讨论、报告问题和提交代码。

    +
  • +
  • +

    部署方式: RSSHub 可以自行部署,用户可以在自己的服务器上搭建RSSHub实例,以便更好地控制和定制生成的RSS源。

    +
  • +
+

确定RSS客户端

+

RSS客户端非常丰富,包括 Android 端,IOS 端,Windows 端,linux 端,浏览器插件,甚至 Vscode 插件(用来摸鱼)等等。这里推荐一些阅读器,当然,也可以选择类似 Feedly 的服务商。

+
    +
  • +

    Android:News,在Fdorid里可下载,中文名为“新闻”,界面简洁,功能全面,支持本地或连接自建服务端。

    +
  • +
  • +

    IOS:Inoreader, 其提供了方便的阅读体验,支持离线阅读、标签和快速搜索。

    +
  • +
  • +

    Windows:Fluent Reader,在github上开源,界面优雅,支持本地或连接自建服务端。

    +
  • +
  • +

    linux:Fluent Reader或Newsboat, 是 Newsbeuter 的一个分支,一款文本控制台 RSS/Atom 订阅阅读器。

    +
  • +
+

自建RSS服务端

+

开源的RSS服务端软件可以用来搭建个人的RSS阅读服务:

+
    +
  • +

    FreshRSS: FreshRSS 是一款简单易用的自建 RSS 服务端软件。它提供了丰富的功能,包括标签、筛选器、阅读统计等,并支持多用户。

    +
  • +
  • +

    Miniflux: Miniflux 是一个轻量级的 RSS/Atom 阅读器服务,支持自建。它采用 Go 语言编写,具有快速响应和简洁的用户界面。

    +
  • +
  • +

    Tiny Tiny RSS (tt-rss): Tiny Tiny RSS 是一款功能丰富的自建RSS服务端软件,提供了类似于 Google Reader 的界面,并支持标签、过滤器、插件等。

    +
  • +
  • +

    Selfoss: Selfoss 是一款支持多种数据源(包括RSS)的自建聚合器。它的界面简洁,支持标签、过滤器和插件,同时也提供了跨平台的客户端。

    +
  • +
  • +

    Miniflux 2: 不要与上面提到的 Miniflux 混淆,Miniflux 2 是 Miniflux 的一个全新版本,同样支持自建 RSS 服务。

    +
  • +
+

这里以MiniFlux为例,其优势在与:

+
    +
  • +

    程序设计极简,不处理任何订阅之外的事情。

    +
  • +
  • +

    程序无外部依赖,运行性能高。

    +
  • +
  • +

    支持自动抓取并缓存图片,加速浏览。

    +
  • +
  • +

    有限支持自动将摘要替换为全文进行抓取。

    +
  • +
  • +

    支持多账号登录,支持 Fever API ,允许客户端从外部登录。

    +
  • +
  • +

    支持集成 PinBoard 、Instapaper、 Pocket、Wallabag、Nunux Keeper 等服务。

    +
  • +
  • +

    提供 Open API、书签快速订阅脚本。

    +
  • +
  • +

    维护者和社区相对活跃,更新频率高。

    +
  • +
+

步骤:

+

1.安装docker 和docker-compose(略)

+

2.Docker 安装 miniflux:

+

(1)创建并进入你想安装 Miniflux 的文件夹:

+

mkdir ~/miniflux # 在根目录创建名为miniflux的文件夹

+

cd ~/miniflux # 进入miniflux文件夹

+

(2)创建docker-compose.yml文件:

+

nano docker-compose.yml # 使用nano编辑器创建,会自动打开文件以写入内容

+

(3)在文件中写入以下内容并保存:

+
version: '3.4'
+
+services:
+
+ miniflux:
+
+ image: miniflux/miniflux:latest
+
+ ports:
+
+ - "127.0.0.1:8080:8080" #调整一:增加localhost ip 并改port为8080
+
+ depends_on:
+
+ - db
+
+ environment:
+
+ - DATABASE_URL=postgres://miniflux:secret@db/miniflux?sslmode=disable
+
+ - RUN_MIGRATIONS=1
+
+ - CREATE_ADMIN=1
+
+ - ADMIN_USERNAME=admin # 登录Miniflux的用户名,可自定义
+
+ - ADMIN_PASSWORD=password # 登录Miniflux的密码,可自定义,至少6位
+
+ - "BASE_URL=https://enter.your.url" # 调整二:输入想用来访问Miniflux的域名
+
+ healthcheck:
+
+ test: ["CMD", "/usr/bin/miniflux", "-healthcheck", "auto"]
+
+ db:
+
+ image: postgres:latest
+
+ environment:
+
+ - POSTGRES_USER=miniflux
+
+ - POSTGRES_PASSWORD=secret
+
+ volumes:
+
+ - miniflux-db:/var/lib/postgresql/data
+
+ healthcheck:
+
+ test: ["CMD", "pg_isready", "-U", "miniflux"]
+
+ interval: 10s
+
+ start_period: 30s
+
+volumes:
+
+ miniflux-db:
+
+

该 docker-compose.yml 文档内容基于 Miniflux 官方文档 ,并在细节上进行了调整。调整有两处:一是将 port 改为127.0.0.1:8080:8080,主要目的是错开常用port 80,并调整 localhost 为127.0.0.1来跟 nginx 的设置一致(如不调整, miniflux 将使用0.0.0.0,无法顺利运行 nginx );二是在 miniflux 的environment 中加入新的 configuration BASE_URL,请将内容换为你想用来访问 Miniflux 的域名。

+

//如何用 nano 保存文件:可以使用 ctrl+X,在退出编辑时,选择Y来保存所有更改,再敲一次回车便可以回到命令行。//

+

(4)运行以下代码进行安装:

+

docker-compose up -d

+

在浏览器中访问服务器ip:端口号(如http://123.45.67.890:8080),如显示登录界面,即代表安装成功。域名解析和反代步骤略。

+

后记

+

RSS源

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-runer-1/index.html b/public/about-runer-1/index.html new file mode 100644 index 0000000..205e13e --- /dev/null +++ b/public/about-runer-1/index.html @@ -0,0 +1,257 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:跑步笔记(一)

+ + + + + + +
+

前言 最近读得<<亮哥跑经>>一书,遂迷上跑步;奈何体重偏高,略微有些吃力.以下是一些笔记:

+ +
+

为啥有人跑两步就喘?

+
+
    +
  • 运动基础薄弱
  • +
+

再慢的跑步,它也比快走的强度要大。跑步虽然很简单,但它并不是低强度的运动。

+
    +
  • 呼吸方法错误
  • +
+

跑步时需要更多的氧气,如果呼和吸的量不均等,吐气比吸的要多,身体没有充分地进行气体交换,就会气喘吁吁。

+
    +
  • 呼吸肌能力较弱
  • +
+

大基数体重的人,腹部往往很胖,身体的呼吸系统较弱。内脏脂肪多,呼吸肌就像吹大的气球一样,被撑薄了,相应的,它收缩和扩张的能力就会下降,所以大体重的人跑步更容易喘。而且除了容易喘之外,他们跑步也更容易岔气。

+
+

正确的呼吸方法是什么?

+
+
    +
  • +

    建议初学者采用两步一吸两步一呼的方式。

    +
  • +
  • +

    等跑了一段时间,心肺功能和整体体能加强之后,可以改为三步一吸三步一呼。

    +
  • +
  • +

    需要注意的是,最好口鼻同时呼吸,才能使充足氧气吸入

    +
  • +
+
+

冬天跑步注意事项

+
+
    +
  • +

    冬天户外跑时,因为天气比较冷,为了防止冷空气进入我们的身体,可以带一个薄薄的口罩。

    +
  • +
  • +

    不要秋天的时候都没跑,到冬天最冷的时候突然出去跑步了。也不要顶风跑,这样你的呼吸系统是受不了的。

    +
  • +
  • +

    冬天跑步的时候,可以用舌尖顶住上牙膛,过滤加温一下冷空气,免得空气直灌入身体,造成肠胃不适。

    +
  • +
+
+

为什么会岔气?

+
+
    +
  • +

    岔气,简单来说,就是呼吸肌痉挛(抽筋)了。

    +
  • +
  • +

    当呼吸肌的能力不足以支撑你的身体这样强度运动时,就会通过痉挛的方式告诉你,你需要停下来或者减慢速度。

    +
  • +
  • +

    平时可以配合做一些腰腹部的核心训练,比如说卷腹、平板支撑等,多练习腹部呼吸法,这样在加强核心力量的同时,也加强了呼吸肌的能力。

    +
  • +
  • +

    跑步之前,要做好充分的热身,不要上来就加速跑,逐渐平缓地提升呼吸节奏,你得让呼吸肌有适应的过程。

    +
  • +
  • +

    如果跑步时出现了岔气情况,可以放慢跑步速度;严重的话,可以停下来调整呼吸,并且身体向相反方向伸展,右侧岔气的话,那就向上伸直右侧手臂,并向左侧伸展 15~30 秒.

    +
  • +
+
+

跑步前期很难坚持,怎么办?

+
+
    +
  • +

    刚开始跑,心肺体能都还跟不上,那可能跑起来不太有成就感,没有正反馈,也不好坚持。因此,需要制定合理的跑步计划(时间/距离)

    +
  • +
  • +

    从跑够 10 分钟开始的。之后每周的运动强度可以比前一周提高 5%。

    +
  • +
  • +

    无论是跑步还是健身,训练时长最好控制在 1 个小时之内,因为 1 个小时的运动会让我们身心都得到满足.

    +
  • +
  • +

    在前期跑步的时候,不要跑上坡路,上坡路非常累.

    +
  • +
  • +

    另外可以通过听音乐、给跑步赋予意义和仪式感、装备奖励等方式,帮助自己度过刚开始跑时的枯燥期。

    +
  • +
+
+

Done

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-runer-2/index.html b/public/about-runer-2/index.html new file mode 100644 index 0000000..e681d9a --- /dev/null +++ b/public/about-runer-2/index.html @@ -0,0 +1,250 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:跑步笔记(二)

+ + + + + + +
+

前言 最近读得<<亮哥跑经>>一书,遂迷上跑步;奈何体重偏高,略微有些吃力.以下是一些笔记:

+

关于跑姿:

+
+

摆臂

+
+
    +
  • +

    摆臂的主要目的,是对抗腿的阻力,来保持我们的身体平衡,让身体向正前方笔直前行。

    +
  • +
  • +

    摆臂和步频是紧密相关的。所以你看那些短跑运动员,他们上肢力量也很发达,因为他们短跑时速度很快,步频很大,如果没有相应的摆臂,他们身体会不平衡.

    +
  • +
  • +

    正确的摆臂应该是什么样的呢?既然我们是向前跑,那么摆臂也应该是垂直向前的,而不是在胸口前左右交叉的,因为你左右摆臂的时候,等于给身体一个左右旋转的力,实际上这消耗了多余的能量,对于腰腹肌肉及腰椎压力也比较大,跑的也不快也不长久。

    +
  • +
  • +

    正确的摆臂应该是肩膀放松状态下,以肩关节为轴的,大臂和小臂成 90 度角,大臂带动小臂前后垂直摆动。 抬起时,大拇指不要超过眉毛,回来时,大拇指不要越过躯干。

    +
  • +
+
+

常见的错误摆臂方式

+
+
    +
  • +

    双臂在身前交叉,我称之为“戳鼻孔跑”。当你的双臂不是垂直向前用力,而是左右旋转的时候,身体会消耗多余能量。

    +
  • +
  • +

    只摆小臂,不摆大臂。跑步时把大臂夹得特别紧,而且摆臂是以肘关节为轴了,这是不对的。

    +
  • +
  • +

    不摆手臂,摆动躯干。完全只是靠摆动躯干的方式在维持平衡,这样会造成能量过度损失,而且对腰椎压力也比较大。

    +
  • +
  • +

    摆臂高度不对,比如说摆臂过大,或是一面高一面低。摆臂过大是短跑的摆臂方式,长跑的摆臂,向前手指不超过眉梢、向后不超过躯干。

    +
  • +
  • +

    摆臂一面高一面低,一般我们戴臂包、手中握手机或水瓶等容易出现这个问题。摆臂是帮我们平衡的,如果你的左右摆臂高度不一样,那跑姿一定是变形的,也就是说身体左右受力是不均匀的,这时很容易导致身体的一侧肌肉紧张,出现像跑步膝等身体损伤.

    +
  • +
+
+

摆腿

+
+
    +
  • +

    看一个人摆腿对不对,就看他是用髋关节跑还是膝关节跑。

    +
  • +
  • +

    正确的长跑姿势,应该是核心收紧,臀大肌和大腿后侧肌肉发力,以髋关节为轴,带动膝关节和踝关节向前跑动,小腿只是辅助性肌肉,它发力不多。所以长跑运动员基本上臀部都是很翘的,而小腿纤细。

    +
  • +
  • +

    如果一直屈髋“坐着跑”,跑步时就会经常出现重心不稳的情况,而且地面给你带来的冲击力,你不能很好地将它传导到臀部,也就是说,这些冲击力都消耗在了膝关节这里。这样的话,一是你很难跑得长久,二是容易把小腿跑粗,三是全身的压力都集中在膝关节,容易带来一些慢性损伤。

    +
  • +
+
+

着地

+
+
    +
  • +

    跑步的着地方式主要有三种:前脚掌、中脚掌和后脚掌。如果我们是长跑的话,主要采用的是后脚跟着地和中足着地的方式。

    +
  • +
  • +

    前脚掌着地会帮助我们跑步提速,但是大众跑者跑长跑,不是比谁跑的快,而是看谁跑得更健康、更安全、更节能。

    +
  • +
+
+

前倾跑 & 低头族

+
+
    +
  • +

    跑步时腰疼或者下背部疼痛,其实这主要和你跑步时身体前倾了有关。因为当你身体前倾时,你的屈髋肌群,也就是胯骨部位会过度紧张,你的下背部肌肉会被反向拉长,它的压力就会增加。这就好比你背个书包去跑步,背部肌肉很容易疲劳的。

    +
  • +
  • +

    而且当你身体前倾的时候,你的髋关节不能很好的帮你做功,身体容易左右扭动,时间长了也容易引起腰部肌肉酸疼。

    +
  • +
  • +

    还有的人是低头跑,如果有这个情况,可以在跑步之前做一些颈部伸展;跑步时,不要探头,稍微收下巴,眼睛可以平视前方 50 米左右地方,这样就可以很好地解决这个问题了。

    +
  • +
+
+

Done

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-server-set/index.html b/public/about-server-set/index.html new file mode 100644 index 0000000..8e58eb3 --- /dev/null +++ b/public/about-server-set/index.html @@ -0,0 +1,545 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:服务器初始化与安全设置

+ + + + + + +
+

前言 本文记录服务器常用操作步骤。

+

Doamin

+

建站不一定需要服务器、域名和备案。尤其不要买腾讯云,不要买CN域名;备案过程要填很多个人信息,且一周没有解析网站,备案就会自动注销。

+
    +
  • +

    cn 域名没有隐私保护(whois protection)。国内域名注册商说的隐私保护根本是自欺欺人,在它们隐私保护就是在自己的查询服务隐藏注册人信息。但在别的地方是能查到的,在中国互联网络信息中心可以查到每个 cn 域名注册人的姓名和邮箱。

    +
  • +
  • +

    注册 cn 域名必须使用真实身份信息。要是你想用假信息注册来保护隐私,那就太天真了。审核的时候不会通过的。真的不想用自己的信息注册的话,要么以公司名义注册,但公司的法定代表人还是能查到的。要么叫别人注册域名之后给你用,可谁愿意冒这种风险呢。

    +
  • +
  • +

    cn 域名无法删除。如果你觉得 cn 域名暴露了你的隐私,那对不起,这是不能注销的3。你只能修改邮箱地址,然后等到它过期。或者转让给别人,不过感觉把别人推到火坑里不太好啊。

    +
  • +
  • +

    cn 域名有被停用的风险。2008 年,有人以跳水奥运冠军吴敏霞拼音注册了 wuminxia.cn,结果被中国互联网络信息中心(CNNIC)回收了域名,并转交给国家体育总局。此域名在 2021 年 2 月 28 日被优视科技注册,呵呵。2009 年,牛博网被域名注册商万网停止解析。

    +
  • +
+

VPS

+
# 更新系统
+apt update && apt upgrade -y
+apt install wget curl vim sudo neofetch
+# 添加普通用户并赋予sudo
+adduser xxx
+sudo usermod -aG sudo xxx
+
+

BBR

+
    +
  • 查询系统所支持的拥塞控制算法
  • +
+
sysctl net.ipv4.tcp_available_congestion_control
+
+
    +
  • 查询正在使用中的拥塞控制算法(Linux 绝大部分系统默认为 Cubic 算法)
  • +
+
sysctl net.ipv4.tcp_congestion_control
+
+
    +
  • 指定拥塞控制算法为 bbr
  • +
+
echo net.ipv4.tcp_congestion_control=bbr >> /etc/sysctl.conf && sysctl -p
+
+

Safe

+
+

使用密码登录:更换SSH端口+安装UFW+安装Fail2ban +使用密钥登录:不用额外操作

+
+

更换SSH端口

+

使用root账户或已经有sudo权限的用户登录到系统。

+

打开SSH配置文件sshd_config,可以使用文本编辑器如nano或vi。以下是使用nano编辑器的示例:

+
sudo vim /etc/ssh/sshd_config
+
+

在配置文件中找到以下行:

+
Port 22
+
+

这是SSH默认的端口号,你可以将其更改为你想要的任何未被占用的端口号。例如,将端口更改为2222:

+
Port 2222
+
+

保存并关闭文本编辑器。重新启动SSH服务,以应用更改:

+
sudo service ssh restart
+
+

或者,如果你的系统使用systemd,可以使用以下命令:

+
sudo systemctl restart ssh
+
+

安装 UFW

+
sudo apt install ufw
+
+

如果你在远程位置连接你的服务器,在启用 UFW 防火墙之前,你必须显式允许进来的 SSH 连接。否则,你将永远都无法连接到机器上。

+
sudo ufw allow 22/tcp
+
+
+

如果 SSH 运行在非标准端口,你需要将上述命令中的 22 端口替换为对应的 SSH 端口。

+
+

启动 UFW

+
sudo ufw enable
+
+

安装 Fail2ban

+
sudo apt-get install fail2ban
+
+

2、Debian 12 及以上的版本需要手动安装 rsyslog

+
sudo apt-get install rsyslog
+
+

3、启动 Fail2ban 服务

+
sudo systemctl start fail2ban
+
+

4、开机自启动

+
sudo systemctl enable fail2ban
+
+

5、查看 Fail2ban 服务状态。

+
sudo systemctl status fail2ban
+
+

改为密钥登录

+
    +
  • 执行以下命令生成.pub后缀的公钥和无后缀的密钥:
  • +
+
ssh-keygen
+
+

注意不同密钥对名称不能相同;同时可以为这两个文件用密码加密;

+
    +
  • +

    随后将.pub后缀的公钥中的内容写入服务器的~/.ssh/authorized_keys中;

    +
  • +
  • +

    使用以下命令编译服务器的SSH配置:

    +
  • +
+
vim /etc/ssh/sshd_config
+
+

将其中的该行改为PasswordAuthentication no,保存退出;随后使用

+
sudo systemctl restart sshd
+
+

重启SSH即可禁用密码登录;

+
    +
  • +

    PermitRootLogin一栏改为PermitRootLogin prohibit-password,即可实现仅root用户密钥登录;

    +
  • +
  • +

    使用以下命令查看输出,

    +
  • +
+
sudo cat /etc/ssh/sshd_config | grep -E 'PasswordAuthentication|PubkeyAuthentication'
+
+

如有PasswordAuthentication no → 禁用密码登录以及PubkeyAuthentication yes → 允许密钥登录则成功。

+
+

注意authorized_keys的权限为600,如果不是则需要改正:chmod 600 ~/.ssh/authorized_keys

+
+

Docker

+

脚本安装

+

Docker 官方提供了一个安装脚本,可以自动选择适当版本,并规避仓库问题:

+
curl -fsSL https://get.docker.com -o get-docker.sh
+sudo sh get-docker.sh
+
+

这个脚本会为你的系统自动选择合适的安装方式。

+

卸载 Docker

+

要删除所有 Docker 容器和 Docker 本身,可以按照以下步骤操作:

+
    +
  1. 首先停止所有正在运行的容器:
  2. +
+
docker stop $(docker ps -aq)
+
+
    +
  1. 删除所有容器
  2. +
+

删除所有容器(包括停止的容器):

+
docker rm $(docker ps -aq)
+
+
    +
  1. 删除所有镜像
  2. +
+
docker rmi $(docker images -q)
+
+
    +
  1. 删除所有网络
  2. +
+
docker network prune -f
+
+
    +
  1. 删除所有未使用的卷
  2. +
+
docker volume prune -f
+
+
    +
  1. 卸载 Docker
  2. +
+

最后,如果您希望完全删除 Docker 本身,可以执行以下命令:

+
sudo apt-get purge docker-ce docker-ce-cli containerd.io
+sudo apt-get autoremove --purge
+sudo rm -rf /var/lib/docker
+sudo rm -rf /etc/docker
+
+

这些命令会卸载 Docker 软件并删除 Docker 数据目录。

+

Docker 常用命令

+
docker-compose up -d    #在后台启动容器
+docker-compose ps       #查看正在运行的容器
+docker-compose down     #停止并移除所有运行中的容器
+docker-compose stop     #停止容器,但保留数据和卷
+docker pull <镜像名称>:latest #拉取最新镜像
+docker-compose build    #更新镜像后重新构建
+docker-compose logs     #查看日志
+docker image prune -a   #删除所有未被容器使用的镜像
+
+

常用环境

+
    +
  • ALL
  • +
+
apt install curl wget gpg vim nano sudo neofetch openssh-server
+
+
    +
  • C/C++
  • +
+
sudo apt install build-essential gdb cmake clangd clang-format libstdc++-dev
+
+
    +
  • Miniconda
  • +
+
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
+bash Miniconda3-latest-Linux-x86_64.sh
+
+
    +
  • UV
  • +
+
curl -LsSf https://astral.sh/uv/install.sh | sh
+
+
    +
  • Docker
  • +
+
curl -fsSL https://get.docker.com -o get-docker.sh
+sudo sh get-docker.sh
+
+
    +
  • OpenCV
  • +
+
sudo apt install tree libx11-dev libgtk-3-dev freeglut3-dev libopencv-dev libdlib-dev
+
+
    +
  • Vmware
  • +
+
sudo apt install open-vm-tools
+sudo apt install open-vm-tools-desktop
+
+
+

Vscode无法连接:需要删除本地存储的错误密钥,powershell:

+
+
(Get-Content "$env:USERPROFILE\.ssh\known_hosts") | 
+Where-Object { $_ -notmatch '<你的IP>' } | 
+Set-Content "$env:USERPROFILE\.ssh\known_hosts"
+
+

1panel

+

执行如下命令一键安装 1Panel:

+
curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && sudo bash quick_start.sh
+
+

禁用 IPv6

+

手动 禁用 VPS 的 IPv6 命令:

+
sysctl -w net.ipv6.conf.all.disable_ipv6=1
+sysctl -w net.ipv6.conf.default.disable_ipv6=1
+
+

如果想重启系统也生效, 执行:

+
echo 'net.ipv6.conf.all.disable_ipv6=1' >> /etc/sysctl.conf
+echo 'net.ipv6.conf.default.disable_ipv6=1' >> /etc/sysctl.conf
+
+

手动 启用 VPS 的 IPv6 命令:

+
sysctl -w net.ipv6.conf.all.disable_ipv6=0
+sysctl -w net.ipv6.conf.default.disable_ipv6=0
+
+

重新载入 sysctl 配置

+
sysctl --system # reload sysctl
+
+

如果重载, 还无效果, 可能要 reboot 重启下. +查看 VPS 的 IPv6 信息

+
ip -6 addr show scope global
+
+或者 curl ipv6.ip.sb
+
+

IP证书申请部署

+
    +
  • +

    ZeroSSL 中申请一个90天的证书;

    +
  • +
  • +

    然后在VPS上输入以下命令:

    +
  • +
+
mkdir -p ./.well-known/pki-validation
+
+
    +
  • +

    随后在ZeroSSL中将所给出的类似B992F08CB46748D02E4C553A4038BC.txt复制;

    +
  • +
  • +

    将从ZeroSSL下载得到的文件打开,复制里面的东西形成以下的格式:将pki-validation/之后EOF之前的内容替换为你自己的。

    +
  • +
+
cat << EOF | sudo tee ./.well-known/pki-validation/B992F08CB46748D02E4C553A4038BC.txt
+254563C20918258D661E7D43D6A43A2A258857E191977DD5F740FBB9ABD25279
+comodoca.com
+ca5792984e3f0a1
+EOF
+
+

随后在VPS上运行该命令。

+
    +
  • 开启一个临时HTTP服务器:
  • +
+
python3 -m http.server 80
+
+
    +
  • 随后即可在ZeroSSL中验证证书并开启SSL。
  • +
+

忘记密码怎么办

+

通过恢复模式 (Recovery Mode) 修改用户权限:

+
    +
  • +

    重启计算机,按住 Shift 键进入 GRUB 菜单(或者按 Esc 键)。

    +
  • +
  • +

    在 GRUB 菜单中,选择Advanced options for Ubuntu然后选择带有recovery mode的内核版本。

    +
  • +
  • +

    进入恢复模式后,选择root – Drop to root shell prompt进入 root shell(不需要密码)。

    +
  • +
  • +

    挂载文件系统为可写模式:

    +
  • +
+
mount -o remount,rw /
+
+
    +
  • 将用户添加到 sudo 组:
  • +
+
usermod -aG sudo 用户名
+
+
    +
  • 重启计算机:
  • +
+
reboot
+
+

更换内核

+

以Xanmod为例:

+
    +
  1. 添加 XanMod 仓库密钥和源
  2. +
+
echo 'deb [signed-by=/usr/share/keyrings/xanmod.gpg] http://deb.xanmod.org releases main' | sudo tee /etc/apt/sources.list.d/xanmod.list
+curl -fsSL https://dl.xanmod.org/gpg.key | gpg --dearmor | sudo tee /usr/share/keyrings/xanmod.gpg > /dev/null
+
+
    +
  1. 更新软件包列表
  2. +
+
sudo apt update
+
+
    +
  1. 搜索可用内核
  2. +
+
apt search xanmod
+sudo apt install linux-image-6.8.6-x64v3-xanmod1 linux-headers-6.8.6-x64v3-xanmod1
+
+

常见 XanMod 内核后缀含义对比

+ + + + + + + +
后缀示例含义简述适合用途
xanmod1, xanmod2, …主线 XanMod 版本编号(带通用优化)桌面、通用、游戏
x64v3-xanmod1针对 x86_64-v3 架构优化(AVX2 以上指令集)高性能桌面、较新 CPU(2011+)
rt-xanmod1实时(RT)内核,用于极低延迟任务音频制作、工业控制
lts-xanmod1长期支持版本(LTS)服务器、稳定性优先
edge-xanmod1更前沿、不稳定的测试版本喜欢尝鲜的高级用户
x64v2-xanmod1, x64v4-…针对特定 微架构(CPU 指令集) 的优化版本有特定硬件支持的系统
+

你可以用以下命令检测你的 CPU 是否支持 x64v3

+
lscpu | grep avx2
+
+

如果输出中有 avx2,就可以用 x64v3 版本。

+
    +
  1. 更新 GRUB 并重启
  2. +
+
sudo update-grub
+sudo reboot
+uname -r
+
+
    +
  1. 移除旧内核(可选)
  2. +
+

查看已安装内核:

+
dpkg --list | grep linux-image
+
+

移除旧的:

+
sudo apt remove linux-image-5.10.0-26-amd64
+
+
+
    +
  1. 自动选择 XanMod 为默认(可选)
  2. +
+

如果你想默认引导到 XanMod 内核:

+

编辑 /etc/default/grub

+
GRUB_DEFAULT="Advanced options for Debian>Debian, with Linux 6.8.6-x64v3-xanmod1"
+
+

然后:

+
sudo update-grub
+
+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-shortcut-key/index.html b/public/about-shortcut-key/index.html new file mode 100644 index 0000000..283425e --- /dev/null +++ b/public/about-shortcut-key/index.html @@ -0,0 +1,422 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:常用实用快捷键

+ + + + + + +
+

前言 在日常使用浏览器时,掌握一些快捷键和技巧可以节省大量时间,提高工作和学习效率。通过学习和实践,能够更加轻松地应对各种网页浏览场景,让浏览器成为工作和学习的得力助手。

+

浏览器快捷键

+

常用

+ + + + + + + + + + + +
快捷键描述
Ctrl + A全选
Ctrl + C复制
Ctrl + X剪切
Ctrl + V粘贴
Ctrl + F查找
Ctrl + Q退出
Ctrl + T新建标签页
Ctrl + W关闭标签页
Ctrl + N新建窗口
Ctrl + Shift + P新建隐私浏览窗口
+

历史

+ + + + +
快捷键描述
Ctrl + H历史侧栏
Ctrl + Shift + H我的足迹窗口(历史)
Ctrl + Shift + Del清除最近历史记录
+

书签

+ + + + + +
快捷键描述
Ctrl + D将此页加为书签
Ctrl + I页面信息
Ctrl + Shift + O显示全部书签(我的足迹窗口)
Ctrl + B / Ctrl + Shift + B书签侧栏 / 顶栏
+

下载与插件

+ + + +
快捷键描述
Ctrl + Shift + Y下载
Ctrl + Shift + A附加组件 / 插件
+

控制台与开发

+ + + + + + + + +
快捷键描述
Ctrl + Shift + KWeb 控制台
Ctrl + Shift + C查看器
Shift + F7样式编辑器
Shift + F5分析器
Ctrl + Shift + E网络
Ctrl + U页面源码
Ctrl + Shift + J浏览器控制台
+

标签页与界面

+ + + + + + + + + + + +
快捷键描述
Ctrl + S界面保存
Ctrl + +放大
Ctrl + -缩小
Ctrl + 0重置缩放
Ctrl + K / J搜索
Ctrl + Home / End到文件头 / 尾
Ctrl + Page Up切换到左边标签页
Ctrl + Page Down切换到右边标签页
Ctrl + Shift + Page Up当前标签页左移
Ctrl + Shift + Page Down当前标签页右移
+

其他操作

+ + + + + + + + +
快捷键描述
Alt + SpaceKDE 搜索栏
Alt + → / ←前进 / 后退
Alt + 数字键选择标签页(1–8)
Alt + M静音
End到达页尾
Home到达页首
F6地址栏
+

VS Code 快捷键

+

界面概览

+ + + + + + + + +
快捷键描述
cmd + shift + e文件资源管理器
cmd + shift + f跨文件搜索
ctrl + shift + g源代码管理
cmd + shift + d启动和调试
cmd + shift + x扩展管理
cmd + shift + p查找并运行所有命令
cmd + j打开、关闭面板
+

命令行的使用

+ + + + + + +
命令描述
code $path新窗口中打开文件或文件夹
code -r $path窗口复用打开文件
code -r -g $file:lineno打开文件并跳转到指定行
code -r -d $file1 $file2比较两个文件
ls code -查看可用命令
+

光标移动

+ + + + + +
快捷键描述
option + 左/右方向键按单词移动光标
cmd + 左/右方向键移动到行首/行尾
cmd + shift + \在花括号之间跳转
cmd + 上/下方向键移动到文档首/尾
+

文本选择

+
    +
  • 使用 shift + 光标移动 进行文本选择。
  • +
+

删除操作

+ + + + + +
快捷键描述
cmd + fn + del删除到行尾
cmd + del删除到行首
option + del向前删除单词
option + fn + del向后删除单词
+

代码行编辑

+ + + + + + + + + + + + + + + +
快捷键描述
cmd + shift + k删除行
cmd + x剪切行
cmd + enter在当前行下方插入新行
cmd + shift + enter在当前行上方插入新行
option + 上/下方向键移动当前行
option + shift + 上/下方向键复制当前行
cmd + /注释/取消注释当前行
option + shift + a注释/取消注释代码块
option + shift + f格式化代码
cmd + k cmd + f格式化选中代码
ctrl + t调换光标前后字符
cmd + shift + p + transform to up/low case转换大小写
ctrl + j合并代码行
cmd + u撤销光标移动
+

创建多个光标

+
    +
  • 使用鼠标:option + 鼠标左键
  • +
  • 使用键盘:
  • +
+ + + + +
快捷键描述
cmd + option + 上/下方向键创建多个光标
cmd + d选中相同单词并创建多个光标
option + shift + i在选中的多行后创建光标
+

文件跳转

+ + + +
快捷键描述
ctrl + tab文件标签之间跳转
cmd + p打开文件列表
+

行跳转

+ + +
快捷键描述
ctrl + g跳转到指定行
+

符号跳转

+ + + + + + + + +
快捷键描述
cmd + shift + o当前文件所有符号列表
@:符号分类排列
cmd + t在多个文件中进行符号跳转
cmd + F12跳转到函数的实现位置
shift + F12查看函数引用列表
ctrl + -跳回上一次光标所在位置
ctrl + shift + -跳回下一次光标所在位置
+

代码自动补全

+ + + + + +
快捷键描述
ctrl + space调出建议列表
cmd + shift + space调出参数预览窗口
cmd + .快速修复建议列表
F2函数名重构
+

代码折叠

+ + + + + +
快捷键描述
cmd + option + [最内层折叠
cmd + option + ]最内层展开
cmd + k cmd + 0全部折叠
cmd + k cmd + j全部展开
+

搜索

+ + + + + +
快捷键描述
cmd + f搜索
cmd + g搜索并跳转
cmd + option + f查找替换
cmd + shift + f多文件搜索
+

编辑器操作

+ + + + + + +
快捷键描述
cmd + \拆分编辑器
option + cmd + 左/右方向键编辑器间切换
cmd + 数字键在拆分的编辑器窗口跳转
cmd + /缩放整个工作区
cmd + shift + p + reset zoom重置缩放
+

专注模式

+ + + + + +
快捷键描述
cmd + b打开或关闭侧边栏
cmd + j打开或关闭面板
cmd + shift + p + Toggle Zen Mode切换禅模式
cmd + shift + p + Toggle Centered Layout切换居中布局
+

命令面板

+ + +
快捷键描述
cmd + shift + p打开命令面板
+

命令面板的前缀符号功能:

+
    +
  • ?:列出所有可用功能
  • +
  • >:显示所有命令
  • +
  • @:显示并跳转文件中的符号
  • +
  • @::按类别归类符号
  • +
  • #:显示并跳转工作区中的符号
  • +
  • ::跳转到当前文件中的某一行
  • +
  • edt:显示所有已打开的文件
  • +
  • edt active:显示当前活动组中的文件
  • +
  • ext:插件管理
  • +
  • ext install:搜索和安装插件
  • +
  • task:任务管理
  • +
  • debug:调试功能
  • +
  • term:创建和管理终端实例
  • +
  • view:打开各个 UI 组件
  • +
+

窗口管理

+ + + + +
快捷键描述
ctrl + w关闭当前窗口
ctrl + r切换文件夹
ctrl + r + cmd + enter新建窗口打开文件夹
+

集成终端

+ + + + + +
快捷键描述
`ctrl + ``切换集成终端
`ctrl + shift + ``新建集成终端
cmd + shift + p + Run Active File In Active Terminal在终端中运行当前文件
cmd + shift + p + Run Selected Text In Active Terminal在终端中运行选中文本
+

任务管理

+ + + + +
快捷键描述
cmd + shift + p + run task自动检测可运行的任务
cmd + shift + p + Configure Task配置任务
cmd + shift + b运行默认的生成任务
+

鼠标操作

+
    +
  • +

    文本选择

    +
      +
    • 双击:选中单词
    • +
    • 三击:选中一行
    • +
    • 四击:选中整个文档
    • +
    • 单击行号:选中整行
    • +
    +
  • +
  • +

    文本编辑

    +
      +
    • 拖动选中文本:移动文本
    • +
    • 拖动时按住 option:复制文本
    • +
    +
  • +
  • +

    函数提示

    +
      +
    • 在悬停窗口上按下 cmd:提示函数的实现
    • +
    +
  • +
+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-ventoy/index.html b/public/about-ventoy/index.html new file mode 100644 index 0000000..4119983 --- /dev/null +++ b/public/about-ventoy/index.html @@ -0,0 +1,262 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:Ventoy战斗盘部署

+ + + + + + +
+

前言 ​Ventoy 是一款开源免费的多系统启动盘制作工具,这里说明其主要功能的制作流程。

+

介绍

+

​Ventoy 是一款开源免费的多系统启动盘制作工具,旨在简化操作系统的安装过程。​与传统的启动盘制作方法不同,Ventoy 允许用户将多个操作系统的镜像文件如 ISO、WIM、IMG、VHD(x)、EFI 等直接复制到 U 盘,无需反复格式化或使用专门的工具写入镜像。

+

ventoy

+

目标

+
+

PE启动盘 / ISO系统安装盘 / Win-to-go / Linux-to-go / 文件存储 五功能合一

+
+

制作流程

+
    +
  • 首先在官网下载Ventoy
  • +
  • 随后在language中改为中文显示,可以看到左上角有配置选项
  • +
  • 将分区类型设置为GPT,开启安全启动支持;
  • +
  • 分区格式设置为NTFS;
  • +
  • 随后在分区设置中进行分区,选择在磁盘后保留一段空间,这里的空间将不被分区,即为空闲空间,可以当作普通的文件存储盘;
  • +
  • Ventoy分区则会使用U盘总容量-保留空间-ventoy保留分区的空间新建一个盘,这里可以放ISO、WIM、IMG、VHD(x)、EFI等等
  • +
  • 随后选择磁盘并开始安装;
  • +
  • 制作完成后即可使用 BIOS Legacy模式 或 UEFI 模式启动。
  • +
+

文件存储盘

+

使用DiskGenius或其他磁盘工具,可以看到刚刚制作的磁盘有两个分区:ventoy保留分区(有文件)和Ventoy分区(无文件)以及一个空闲空间。

+

将空闲空间格式化并新建磁盘,随后会出现一个新的可用盘,可以用这个盘进行存储

+

PE启动盘制作

+

将PE的ISO文件放入Ventoy分区即可。常用PE:

+ +

ISO系统安装盘

+

将要安装的系统的ISO镜像放入Ventoy分区即可。常用系统:

+ +

Win-to-go

+

Ventoy 使用名为ventoy_vhdboot插件来支持直接启动 VHD(x) 文件(Win7以上).支持 Legacy BIOS 和 UEFI 模式。支持固定大小以及动态扩展类型的 VHD/VHDX 格式。

+

从下面任意一个链接中下载ventoy_vhdboot.img文件即可(几个链接中的文件都是一样的)。

+ +

把下载后的文件放在U盘第1个分区(就是放ISO文件的分区)的 ventoy 目录下(默认没有这个目录,需手动创建,注意大小写),即 /ventoy/ventoy_vhdboot.img 就可以了。

+

随后将vhd或vhdx后缀的Windows虚拟机镜像放入其中即可出现在启动栏。

+
+

可以使用Virtualbox创建Windows虚拟机并将镜像复制到ventoy中。

+
+

Linux-to-go

+

Ventoy 使用plugin_vtoyboot插件来支持在物理机上直接启动安装了 Linux系统的 vdisk 文件 (vhd/vdi/raw 等)。这种模式的优点有:

+
    +
  • 系统是在真实物理机上运行,并不是在虚拟机里运行,没有性能损失
  • +
  • 同一个 vhd/vdi 文件既可以在 Legacy BIOS 模式下启动,也可以在 UEFI 模式下启动。
  • +
  • Linux系统无需独占一个磁盘或者分区,相当于把一个完整的Linux系统放在一个文件里。 比如,你的主系统是 C 盘里的 Windows 系统,你可以在D盘里放一些
  • +
  • Deepin、UOS、Ubuntu、Arch 等系统的 VHD 文件,想启动哪个选哪个,不用了就把对应的 VHD 文件删除即可。
  • +
+

支持的 vdisk 格式:

+
    +
  • 固定大小的 vhd (注意只能是vhd, 不支持vhdx)
  • +
  • 固定大小的 vdi
  • +
  • Raw Disk 镜像格式
  • +
+

安装 Linux 系统到 vdisk

+

VirtualBox中创建固定大小的 vhd/vdi,注意只支持静态大小的,不支持动态扩展类型的。然后把支持的 Linux 系统安装到 vhd/vdi 中即可。

+

注意:

+
    +
  • 虚拟硬盘必须是全新创建的,不能使用之前用过的。
  • +
  • 新版本的 VirtualBox 在创建虚拟机时不要选择操作系统ISO文件,等创建完虚拟机之后再添加ISO文件进行安装。
  • +
  • 安装系统时,VirtualBox 必须设置为 UEFI 模式
  • +
  • 注意,系统安装完之后不能对虚拟机创建快照,否则会导致 vdi/vhd 无法识别。
  • +
+

有一些系统安装完之后还需要再额外安装一个 grub 的包才可以,否则最终的 vhd/vdi 文件只能在 UEFI 模式下启动,无法在 Legacy BIOS 模式下启动。对于这种,在前面表格最后的 "备注" 一栏有说明,没有特殊说明的就不需要。详见Linux vDisk 文件启动插件

+

在系统下执行 vtoyboot 脚本

+
    +
  • +

    安装完成并启动到 Linux 系统中之后,执行 vtoyboot 脚本。这一步是为了在系统中做一些处理,以支持Ventoy启动。

    +
  • +
  • +

    vtoyboot 是配套 Ventoy 开发的一个项目,单独发布。从 https://github.com/ventoy/vtoyboot/releases 下载压缩包即可。

    +
  • +
  • +

    下载到 Linux 系统中,解压,然后以root权限执行里面的脚本 sudo bash vtoyboot.sh 脚本执行完之后,使用 poweroff 命令关机。

    +
  • +
  • +

    注意 vtoyboot 会经常更新以支持更多的 Linux 版本以及修复 BUG,所以请使用最新版本。

    +
  • +
+
+

如果是对内核、驱动进行了升级、或者类似于通过 dnf update 命令进行了系统的大升级之后, 建议再重新执行一次 vtoyboot 脚本,防止下次重启之后vDisk文件无法启动。

+
+

随后拷贝到U盘,改后缀名为 .vtoy 然后用 Ventoy 启动即可。

+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about-vim/index.html b/public/about-vim/index.html new file mode 100644 index 0000000..19e3b60 --- /dev/null +++ b/public/about-vim/index.html @@ -0,0 +1,323 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

乱七八糟:Vim编辑器速查

+ + + + + + +
+

前言 Vim 是从早期的 vi 编辑器发展而来的增强版,其名称代表“Vi IMproved”。由荷兰程序员 Bram Moolenaar 于 1991 年首次发布。Vim 是开源软件,支持多种操作系统,包括 Unix、Linux、Windows 和 macOS 等。

+ +
+

一份优秀的 Vim 速查表

+
+

翻译自https://vimsheet.com/

+
+

我整理了一份我每天使用的 Vim 基本命令列表,并提供了一些配置建议,使 Vim 更加实用。因为没有配置的 Vim 使用起来会比较痛苦。

+

基础命令

+

光标移动(普通模式/可视模式)

+
    +
  • h j k l:左、下、上、右移动
  • +
  • w / b:下一个/上一个单词
  • +
  • W / B:下一个/上一个以空格分隔的单词
  • +
  • e / ge:下一个/上一个单词的结尾
  • +
  • 0 / $:行首/行尾
  • +
  • ^:行首第一个非空白字符(等同于 0w
  • +
+

编辑文本

+
    +
  • i / a:在光标处/之后进入插入模式
  • +
  • I / A:在行首/行尾进入插入模式
  • +
  • o / O:在当前行下方/上方插入空行
  • +
  • EscCtrl+[:退出插入模式
  • +
  • d:删除
  • +
  • dd:删除整行
  • +
  • c:删除并进入插入模式
  • +
  • cc:删除整行并进入插入模式
  • +
+

操作符

+
    +
  • 操作符也适用于可视模式
  • +
  • d:从光标处删除到移动目标
  • +
  • c:从光标处删除到移动目标,并进入插入模式
  • +
  • y:从光标处复制到移动目标
  • +
  • >:缩进一级
  • +
  • <:取消缩进一级
  • +
  • 操作符可与移动命令组合使用,例如:d$ 删除从光标到行尾的内容
  • +
+

标记文本(可视模式)

+
    +
  • v:进入可视模式
  • +
  • V:进入行可视模式
  • +
  • Ctrl+v:进入块可视模式
  • +
  • EscCtrl+[:退出可视模式
  • +
+

剪贴板操作

+
    +
  • yy:复制整行
  • +
  • p:在光标后粘贴
  • +
  • P:在光标前粘贴
  • +
  • dd:剪切整行
  • +
  • x:删除当前字符
  • +
  • X:删除前一个字符
  • +
  • 默认情况下,d / c 会将删除的内容复制到剪贴板
  • +
+

退出

+
    +
  • :w:保存文件但不退出
  • +
  • :wq:保存并退出
  • +
  • :q:退出(如果有修改会失败)
  • +
  • :q!:强制退出并放弃修改
  • +
+

搜索/替换

+
    +
  • /pattern:搜索 pattern
  • +
  • ?pattern:向上搜索 pattern
  • +
  • n:重复上一次搜索(同方向)
  • +
  • N:重复上一次搜索(反方向)
  • +
  • :%s/old/new/g:全文件替换 old 为 new
  • +
  • :%s/old/new/gc:全文件替换 old 为 new,并逐个确认
  • +
+

常规命令

+
    +
  • u:撤销
  • +
  • Ctrl+r:重做
  • +
+

高级命令

+

光标移动

+
    +
  • Ctrl+d:向下移动半页
  • +
  • Ctrl+u:向上移动半页
  • +
  • }:跳转到下一个段落(空行)
  • +
  • {:跳转到上一个段落(空行)
  • +
  • gg:跳转到文件顶部
  • +
  • G:跳转到文件底部
  • +
  • :[num]:跳转到指定行号
  • +
  • Ctrl+e / Ctrl+y:向下/向上滚动一行
  • +
+

字符搜索

+
    +
  • f [char]:向前移动到指定字符
  • +
  • F [char]:向后移动到指定字符
  • +
  • t [char]:向前移动到指定字符之前
  • +
  • T [char]:向后移动到指定字符之前
  • +
  • ; / ,:重复上一次字符搜索(正向/反向)
  • +
+

编辑文本

+
    +
  • J:将下一行合并到当前行
  • +
  • r [char]:用指定字符替换当前字符(不进入插入模式)
  • +
+

可视模式

+
    +
  • O:移动到块的另一个角
  • +
  • o:移动到标记区域的另一端
  • +
+

文件标签

+
    +
  • :e filename:编辑文件
  • +
  • :tabe:打开新标签页
  • +
  • gt:切换到下一个标签页
  • +
  • gT:切换到上一个标签页
  • +
  • :vsp:垂直分割窗口
  • +
  • Ctrl+ws:水平分割窗口
  • +
  • Ctrl+wv:垂直分割窗口
  • +
  • Ctrl+ww:在窗口间切换
  • +
  • Ctrl+wq:关闭当前窗口
  • +
+

标记

+
    +
  • 标记允许你跳转到代码中的指定位置
  • +
  • m{a-z}:在光标位置设置标记 {a-z}
  • +
  • 大写标记 {A-Z} 是全局标记,可跨文件使用
  • +
  • '{a-z}:跳转到设置标记的行首
  • +
  • '':返回上一个跳转位置
  • +
+

文本对象

+
    +
  • 例如:def (arg1, arg2, arg3),光标在括号内
  • +
  • di(:删除括号内的内容,即“删除最近括号内的内容”
  • +
  • 如果没有文本对象,你需要使用 T(dt) 来实现相同的功能
  • +
+

常规命令

+
    +
  • .:重复上一次命令
  • +
  • 在插入模式下,Ctrl+r 0:插入最近复制的文本
  • +
  • gv:重新选择上一次选中的文本块
  • +
  • %:在匹配的 (){} 之间跳转
  • +
+
+

如果你希望将此速查表保存为 PDF 或打印出来,可以使用 Markdown 编辑器(如 Typora)或在线工具(如 Dillinger)进行导出。

+

此外,Vim 的默认配置可能不够友好,建议你参考以下资源进行配置优化:

+ +

这些插件可以显著提升 Vim 的功能,使其更接近一个完整的 IDE。

+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/about/index.html b/public/about/index.html new file mode 100644 index 0000000..d25e744 --- /dev/null +++ b/public/about/index.html @@ -0,0 +1,209 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

About Me

+ + + + +
+

Welcome to dich' Blog!

+

用电子罗盘,转赛博核桃,勘电磁风水,寻网络龙脉

+
+

一个人应该能够给孩子换尿布、计划一次侵略行动、杀猪、驾驶飞船、设计建筑物、写诗、做会计账目、砌墙、接合断骨、照顾临终的人、执行命令、下达命令、与人合作、独立行动、解方程式、分析一个新问题、施肥、编程、做一餐美味的饭、高效地战斗、勇敢地死去。专业化是为昆虫准备的。 ——罗伯特·海因莱恩

+
+

有事请联系 admin@dich.bid

+

GPG公钥:

+
-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mDMEaFD4ERYJKwYBBAHaRw8BAQdAWahrrdkEPyUXuYxI72vuu10wdzoUflXwgoOP
+W5BDNwy0F2RpY2ggPGJyY2VmeUBnbWFpbC5jb20+iJYEExYKAD4WIQQLzPfdBMio
+WbXLx6aN3u4/oWJWBAUCaFD4EQIbAwUJAeEzgAULCQgHAgYVCgkICwIEFgIDAQIe
+AQIXgAAKCRCN3u4/oWJWBJyIAP9pDBde2tEdppRHn+Qk8tYIsdJHmEdbSiWBRGgq
+oEtqZwD/SlTXOKC8XFBHhXfDQe6HKKfcmOHzI7tCAbEvYzXNPwW4OARoUPgREgor
+BgEEAZdVAQUBAQdAtId5jz2fnDkGUz2b4Y7wqI4yDAgeJgKlmEdxMMVEjgcDAQgH
+iH4EGBYKACYWIQQLzPfdBMioWbXLx6aN3u4/oWJWBAUCaFD4EQIbDAUJAeEzgAAK
+CRCN3u4/oWJWBPrHAQCtfO5kC5XEEcJUCM7hKjC1OMzqE2qlBS3te2rZT3KH0wD/
+dr+m3w+D4q5y5uy1sny6BW6QjjdrQP+ZWUjA3na0jgqZAg0EWpElGwEQAMkauPYV
+lZPeaWC0AUxQJ7EPFVBcuAEnYZ9eXoPvlo74DIuqODCmaj90uBfyhkKcFj4c63WZ
+9eFL5JpJxz7BuIMjLbaaVI1eFE9EvBXW0cUeu86WNu8Jbtn5CxtfyokqtYXmP6AP
+hj1p8hdic//hRXs3eLeeNe1YZRW6i8cLM1WCkbWjzKvg91JX4hKXDPExwgGwoqDi
+ZqrvkyQ4kY0oddzwoQ9Lb1U4oXWzE4g34o46hUaLgNW1iZ/zYJNT3EUb74bAzxvE
+nwsVrueNsS8wuYOWckD2WKt7KjHJxg4uo+MjSUdPf5+qgN68+n91qKstSz3lZq25
+1q5HUL2jnyeCTMBl8BY9O/+qdDrm2dXNaPSfRCk0jPKxcyi0YydhrEgzDX9wW2Ha
+dDyGIUwSKxvwdzjE/quE+d3WUWv51oTrYZmHm9YhXki37AFqCcz+7qECvNTvyvih
+tQ86x+TUwZmlWwusPoZJNEOOi/9Popvd+ys7uBiCKae7wAAtlrdMXLBwOLMpis+z
+HkfHN41ZpjwnbPSq7hM7NwhHTBA+8TxNTgu4piZadHf2Qvw0ofme5+ipkcueufdf
+ocj9rXGZ7D3cxVgCK2c7QpUV+gVcY29hqNAiY7Eh+ldgxHt/o6vTiauYjPpjlyh4
+31TEv8kQapqcgtC6JL6LKeZiyqb7+5YTt7rbABEBAAG0REZyYW5jaXMgQmFueWlr
+d2EgKEEga2V5IGZvciBzaWduaW5nIHBhY2thZ2VzKSA8YmFueWlrd2FmYkBnbWFp
+bC5jb20+iQI3BBMBCAAhBQJakSUbAhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheA
+AAoJEBbi4azG9RJCoasQAMkL3AcIinDXec8/9Tg4MFMKd0/owT9arC0K8UP7yu2S
+/H+G+uYm8lsnjCv2Nlsll8fo2P+QuIsIg4ec7qb6Ng/ZAXvKwILMHsULLcYY1Jv5
+n5k5+DnItUehUSSKTn1haOvL0+3u48PzcCmVHVMsECnW6sUuUnVPE+gtuvwChKWV
+92jLfWkk+jl7FxxCv0b20COCX0MRtIO1Im7oqSgTLQLzKQiK2NxsNmciMBmWhzZm
+X/64eZeidS3VRYmWd0rUdFCXwTDgXeHOwYmlI9la7hmqi1k5i2ILFW2XE4m5+Jtv
+5VIIa1rSB6iOVpsIKb0wFwJhye8ak2ZCQfRLL3Fhwt8M+qri0V9X6EJpa7U6uMUL
+qWl3N6Tt7DMbTFAFfxeykRSzEENGWF3PcyC/KGakuQGhsNJcUInXUhjKKHyUPRpo
+udV14RZoSzLEBepjowUCulRGJ6VIcDpmmCMKmlOBMiErtqyBeLJZ3L6DGgW059bW
+FxPZeyauoO86mZ3eA2WRrm7B1jb/1gCg8IneqOIVp9Vt5yLmfZ5ZrM5m3L/Id7Zs
+dAU0ATYv2YIh3tZWfgG7SKIlv7eBj7Ytwl4ELLHRgyE0mewZen5qxcACxCax6rJw
+aM+jgmnSlyWpt1JuQJBNIdV6UCi3G7fkfQBAmFftF1ZgYTx9/6fiB2bvr3DQkn57
+uQINBFqRJRsBEACt+JgM+FRqK5EDUZEhP0huTAzMdZITBjtDbCNs2UakAVJS8l4C
+P9pulv+E01yAj+ecw++Ke/tKeeUOjzezGihRhpwAstPiquNodkE9MLftkyu9lkIN
+Xvzt6t6fLdIJzE+kB0x8gMphSq0Wp7qjWxDXCyr0SMYD8wLttYIjFogG5YRsQ/j6
+PV+hRexZ+P8l2UoWvtbxDCbNrDLUMEYjK6CZjtXn8qNLzPFSOVNjqZpIm9/BlWZZ
+0WbtpSmzdVL23aGt968RueqcRdqy9+lvw7U8tOUOmjP9zKRN0IADdw0WphYEBfWa
+hxeKmJk+nFR6g3TPQ86xdL3VZsPtqSdVO6O5CdqcVFVyoaebsTZlw/Qz1/6Sy3gJ
+83IezA8kJItk6ZRMiHNVM5+x/z8feFVjnDz+DG3px09vZ/YOi4GF1d0G/dnCf2DF
+l4dH6+Va34KfCwYjnkFPtd8Wj4M8H62UMJrCg81eEcGtlFtKBtkHv8VMRl6I/cYH
+p1uq3eNCy5G7IrIlYyG1zc6xuDun0PZChnkwNWjylfdk0XFGTtASC9WjIjIBD364
+ns/p4j7gJYx5RZspCfytPzjpUtP0N5wEMLoz3KbQsbxAuDxkijV7s1xVrApxk2xG
+rdMeWM5KpbAwlos9yDlb4YYbUrOR+CPBYPTbrQ55wcePV4gOnEmoyrdkYwARAQAB
+iQIfBBgBCAAJBQJakSUbAhsMAAoJEBbi4azG9RJCaEsQAJJB2BXMks73ETSdvIPn
+R9eRFIpXmaYnGOBQnvz+lSlQ+etcjmXbWw8YxKohdeIfuydV1Fug/I/WmlzDDH8B
+1R26Vs0Czr2P64iNJVIhrdjvfPK5fdJXKwSchiJ1SEWahsXXXyQXqOZwMkGMxxFd
+diH4OVsY5q9cM21gXup4WBezFPMtaUvu35QKbwgKntgdJJv/JSc8rWHZQS8p/820
+v8UWxxxbgprbtTvmwMakr70u4FtORWic1UTJ9sCsD4Yw6CbvLyMV8z5vAQhi+lND
+qIzRXEXTfYnZaQ6ddCuTMGF2K1+CyS7/7FA0YwxrjhlxE0XwOgvpvJS/tmK0fB4J
+IvDXgCW/ym2xvGVwLTNu/apeon0Skli4sokl2yVnUMRKGCz7ApjhrNo1kikHKGJw
+8jv6tCTIyJtGobmTaIZGg2N3Owd7QhoBbR80LIFFaAlWgFv2XnLes8wF1xVNmjMI
+jsKO+itYmntg/GPep6hOcFnU/JrsSiVTvmHlpTHqK7q1cZTDV/G5W739m4z00hgw
+zXHD2OOP/LPGEtQWOg+g8g3+KNQzLHZqQO5UScTG2fL99FaXNDv3BZt4e4liGD01
+5oRRZTFV4YPmXVB1x23FhkRQN2Jnt76x9t8QcwKcXWBUOUZg9uJUkIgipxxPEPSC
+NS+riEdhXHgqG76f+wRnkDOK
+=2r/G
+-----END PGP PUBLIC KEY BLOCK-----
+
+ +
+ + +
+ +
+ + + + +
+ + + diff --git a/public/archive/index.html b/public/archive/index.html new file mode 100644 index 0000000..d81a750 --- /dev/null +++ b/public/archive/index.html @@ -0,0 +1,659 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+

Archive

+ + + + + + +
+ +
+ + + + +
+ + + diff --git a/public/atom.xml b/public/atom.xml new file mode 100644 index 0000000..59e0c10 --- /dev/null +++ b/public/atom.xml @@ -0,0 +1,1398 @@ + + + + Dich'blog + 用电子罗盘,转赛博核桃,勘电磁风水,寻网络龙脉 + + + Zola + 2025-06-17T00:00:00+00:00 + https://blog.dich.bid/atom.xml + + 乱七八糟:GPG使用小记 + 2025-06-17T00:00:00+00:00 + 2025-06-17T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-gpg/ + + <p>前言 PGP/GPG 的核心功能——公钥加密、数字签名、信任管理广泛用于各个行业,本文简单说明了其使用方法。</p> + + + + 乱七八糟:Baci实验笔记 + 2025-04-23T00:00:00+00:00 + 2025-04-23T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-baci/ + + <p>前言 ​BACI是一个简化的并发程序模拟器,这里对其语法与运行环境进行说明。</p> + + + + 乱七八糟:lazyvim快速上手 + 2025-04-20T00:00:00+00:00 + 2025-04-20T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-lazyvim/ + + <p>前言 ​LazyVim 是一个基于 Neovim 的现代化配置框架,易于定制和扩展,这里对其介绍并说明使用方法。</p> + + + + 乱七八糟:Aria2各平台使用指南 + 2025-04-15T00:00:00+00:00 + 2025-04-15T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-aria2/ + + <p>前言 Aria2是一款开源、跨平台的命令行界面下载管理器,常常被各种下载器软件使用。</p> + + + + 乱七八糟:Markdown使用快速教程 + 2025-04-08T00:00:00+00:00 + 2025-04-08T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-markdown/ + + <p>前言 本文为 Markdown 教程,内容涵盖 Markdown 的历史、作用、基本语法和显示效果,可以在github将本文的源码拷贝供大家参考和学习。</p> + + + + 乱七八糟:GFS项目考量笔记 + 2025-03-18T00:00:00+00:00 + 2025-03-18T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-gfs/ + + <p>前言 最近nekoray项目归档,考量新的singbox前端时发现这个项目不错,不过在Arch linux中运行有一些小问题,这里做个总结。</p> + + + + 乱七八糟:FRP使用指南 + 2025-03-01T00:00:00+00:00 + 2025-03-01T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-frp/ + + <p>前言 FRP (Fast Reverse Proxy) 是一个用Go语言开发的高性能反向代理应用,可以帮助您轻松地进行内网穿透,对外提供服务.</p> + + + + 乱七八糟:Ventoy战斗盘部署 + 2025-02-14T00:00:00+00:00 + 2025-02-14T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-ventoy/ + + <p>前言 ​Ventoy 是一款开源免费的多系统启动盘制作工具,这里说明其主要功能的制作流程。</p> + + + + 谈天说地:狄奇周刊(二一) + 2025-02-04T00:00:00+00:00 + 2025-02-04T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-21/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。</p> + + + + 谈天说地:狄奇周刊(二十) + 2025-01-25T00:00:00+00:00 + 2025-01-25T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-20/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。</p> + + + + Network的艺术:家庭组网方案与设备选购 + 2025-01-21T00:00:00+00:00 + 2025-01-21T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/network-zuwang/ + + <p>前言 本文介绍一些家庭组网方案和家庭网络升级方案。</p> + + + + 乱七八糟:2024年度总结 + 2025-01-04T00:00:00+00:00 + 2025-01-04T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-2024/ + + <p>前言 又是新的一年,时间流速感觉越来越快了。</p> + + + + 谈天说地:狄奇周刊(十九) + 2024-10-23T00:00:00+00:00 + 2024-10-23T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-19/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。</p> + + + + 谈天说地:狄奇周刊(十八) + 2024-10-13T00:00:00+00:00 + 2024-10-13T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-18/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。</p> + + + + 谈天说地:狄奇周刊(十七) + 2024-10-05T00:00:00+00:00 + 2024-10-05T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-17/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。</p> + + + + 谈天说地:狄奇周刊(十六) + 2024-09-28T00:00:00+00:00 + 2024-09-28T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-16/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。</p> + + + + 谈天说地:狄奇周刊(十五) + 2024-09-21T00:00:00+00:00 + 2024-09-21T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-15/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。</p> + + + + 谈天说地:狄奇周刊(十四) + 2024-09-16T00:00:00+00:00 + 2024-09-16T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-14/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。</p> + + + + 谈天说地:狄奇周刊(十三) + 2024-09-07T00:00:00+00:00 + 2024-09-07T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-13/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。</p> + + + + 谈天说地:狄奇周刊(十二) + 2024-08-29T00:00:00+00:00 + 2024-08-29T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-12/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。</p> + + + + 谈天说地:狄奇周刊(十一) + 2024-08-22T00:00:00+00:00 + 2024-08-22T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-11/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。</p> + + + + 乱七八糟:Vim编辑器速查 + 2024-08-15T00:00:00+00:00 + 2024-08-15T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-vim/ + + <p>前言 Vim 是从早期的 vi 编辑器发展而来的增强版,其名称代表“Vi IMproved”。由荷兰程序员 Bram Moolenaar 于 1991 年首次发布。Vim 是开源软件,支持多种操作系统,包括 Unix、Linux、Windows 和 macOS 等。</p> + + + + 谈天说地:狄奇周刊(十) + 2024-08-15T00:00:00+00:00 + 2024-08-15T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-10/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。</p> + + + + 谈天说地:狄奇周刊(九) + 2024-08-08T00:00:00+00:00 + 2024-08-08T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-9/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。</p> + + + + 谈天说地:狄奇周刊(八) + 2024-08-03T00:00:00+00:00 + 2024-08-03T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-8/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。</p> + + + + 谈天说地:狄奇周刊(七) + 2024-07-26T00:00:00+00:00 + 2024-07-26T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-7/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,每周四更新.PS:因为昨天输入法突发恶疾,所以无法按时更新。</p> + + + + 谈天说地:狄奇周刊(六) + 2024-07-18T00:00:00+00:00 + 2024-07-18T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-6/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,每周四更新.</p> + + + + Network的艺术:Docker建站与反向代理 + 2024-07-14T00:00:00+00:00 + 2024-07-14T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/network-nginx/ + + <p>前言 Docker的出现极大简化了建站流程,较过去的LAMP方式优雅了许多,配合Nginx反向代理可以快速上线HTTPS站点。</p> + + + + 谈天说地:狄奇周刊(五) + 2024-07-11T00:00:00+00:00 + 2024-07-11T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-5/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,每周四更新.</p> + + + + 谈天说地:狄奇周刊(四) + 2024-07-04T00:00:00+00:00 + 2024-07-04T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-4/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,每周四更新.</p> + + + + 谈天说地:狄奇周刊(三) + 2024-06-26T00:00:00+00:00 + 2024-06-26T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-3/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,这周三提前一天更新.</p> + + + + 谈天说地:狄奇周刊(二) + 2024-06-20T00:00:00+00:00 + 2024-06-20T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-2/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,暂定每周四进行更新.</p> + + + + 谈天说地:狄奇周刊(一) + 2024-06-13T00:00:00+00:00 + 2024-06-13T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/weekly/zhoubao-1/ + + <p>前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,暂定每周四进行更新.</p> + + + + 乱七八糟:服务器初始化与安全设置 + 2024-06-12T00:00:00+00:00 + 2024-06-12T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-server-set/ + + <p>前言 本文记录服务器常用操作步骤。</p> + + + + 乱七八糟:跑步笔记(二) + 2024-06-11T00:00:00+00:00 + 2024-06-11T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-runer-2/ + + <p>前言 最近读得&lt;&lt;亮哥跑经&gt;&gt;一书,遂迷上跑步;奈何体重偏高,略微有些吃力.以下是一些笔记:</p> + + + + 乱七八糟:跑步笔记(一) + 2024-06-08T00:00:00+00:00 + 2024-06-08T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-runer-1/ + + <p>前言 最近读得&lt;&lt;亮哥跑经&gt;&gt;一书,遂迷上跑步;奈何体重偏高,略微有些吃力.以下是一些笔记:</p> + + + + 乱七八糟:计算机科学优质视频 + 2024-05-31T00:00:00+00:00 + 2024-05-31T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-cslearning/ + + <p>前言 CSdiy珠玉在前,为CS教育做出了极大贡献.这里分享一些优质的CS学习相关视频.</p> + + + + 乱七八糟:Windows-Jupyter开发Python + 2024-05-31T00:00:00+00:00 + 2024-05-31T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/windows-conda-python/ + + <p>前言 由于 Windows 中开发环境较 linux 复杂,这里总结 Windows 中使用 Jupyter 开发 Python 的环境配置。</p> + + + + 乱七八糟:Windows-VScode开发C/C++ + 2024-05-30T00:00:00+00:00 + 2024-05-30T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/windows-vscode-gcc/ + + <p>前言 由于 Windows 中开发环境较 linux 复杂,这里总结 Windows 中使用 VScode 开发 C/C++ 的环境配置。</p> + + + + 乱七八糟:Windows封装与全自动安装 + 2024-05-29T00:00:00+00:00 + 2024-05-29T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/windows-iso/ + + <p>前言 由于厂商默认安装windows家庭版导致各种问题频发,这里作者封装了一个开箱即用的,全自动安装,激活和优化的Windows11镜像。</p> + + + + 乱七八糟:Windows安装与环境配置 + 2024-05-26T00:00:00+00:00 + 2024-05-26T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/windows-all/ + + <p>前言 由于厂商默认安装windows家庭版导致各种问题频发,这里对 widnows 安装做一个总结,以及附上我个人的windows配置。</p> + + + + 乱七八糟:Windows激活那些事 + 2024-05-25T00:00:00+00:00 + 2024-05-25T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/windows-activation/ + + <p>前言 Windows的正版售价十分昂贵,2025年的今天大部分人都使用着OEM厂商自带的windows系统或自己想办法激活,那么,激活到底是什么原理?</p> + + + + 乱七八糟:Windows常用操作 + 2024-05-24T00:00:00+00:00 + 2024-05-24T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/windows-some-setting/ + + <p>前言 Windows操作系统作为全球最为普及的桌面操作系统之一,其用户界面的设计非常经典,但存在许多不足之处,本篇记录一些常用脚本。</p> + + + + 乱七八糟:常用实用快捷键 + 2024-05-23T00:00:00+00:00 + 2024-05-23T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-shortcut-key/ + + <p>前言 在日常使用浏览器时,掌握一些快捷键和技巧可以节省大量时间,提高工作和学习效率。通过学习和实践,能够更加轻松地应对各种网页浏览场景,让浏览器成为工作和学习的得力助手。</p> + + + + 搭建个人信息流:播客收听指北 + 2024-03-06T00:00:00+00:00 + 2024-03-06T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-podcast-use/ + + <p>前言 讲起播客,许多人第一反应是喜马拉雅,但其实播客的订阅和收听有许多种方式。本文带你了解订阅播客的各种方式,并告诉你市面上有哪些不错的播客客户端可供选择。</p> + + + + 搭建个人信息流:RSS阅读指南 + 2024-03-05T00:00:00+00:00 + 2024-03-05T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-rss-read/ + + <p>前言 RSS 提供了一种数据格式,以 XML(可扩展标记语言)的形式组织信息,包括文章标题、摘要、链接和发布日期等。这些信息形成了所谓的“订阅源”(Feed),用户可以使用RSS阅读器(Feed Reader)来订阅这些源。</p> + + + + 乱七八糟:开源软件与协议 + 2024-03-03T00:00:00+00:00 + 2024-03-03T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-opensource/ + + <p>前言 本文旨在介绍开源以及开源许可证,这些许可证规定了使用、修改和分发开源软件的条件。通过了解不同类型的开源许可证及其特点,读者将能够更好地理解在开发和使用开源软件时的法律和道德责任。</p> + + + + 电子邮件是如何工作的:自建域名邮箱 + 2024-02-22T00:00:00+00:00 + 2024-02-22T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/network-how-email-works-3/ + + <p>前言 poste.io 邮件服务基于 Docker 搭建,用的是 Haraka + Dovecot + SQLite 邮件系统,占用资源较少,安装简单,适合个人使用。</p> + + + + 电子邮件是如何工作的:POP3/IMAP/SMTP + 2024-02-21T00:00:00+00:00 + 2024-02-21T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/network-how-email-works-2/ + + <p>前言 POP3、IMAP 和 SMTP 是用于电子邮件传输的常见协议和服务,这些协议共同构成了电子邮件系统的基础,允许用户接收、发送和管理电子邮件。</p> + + + + 电子邮件是如何工作的:SPF/DKIM/DMARC + 2024-02-20T00:00:00+00:00 + 2024-02-20T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/network-how-email-works-1/ + + <p>前言 在互联网的日常使用中,电子邮件作为一项基础服务扮演着重要的角色。尽管在过去几十年里出现了各种新型的通讯方式,但电子邮件仍然保持着其不可替代的地位。了解电子邮件的工作原理,有助于更好地理解这一基础服务是如何运作的。</p> + + + + Network的艺术:CDN技术与应用 + 2024-02-16T00:00:00+00:00 + 2024-02-16T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/network-cdn/ + + <p>前言 内容分发网络(CDN)是一组分布在不同地理位置的服务器网络,使用户能够就近获取内容,从而降低延迟并缓解源站压力​.</p> + + + + Network的艺术:SSL/TLS证书 + 2024-02-15T00:00:00+00:00 + 2024-02-15T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/network-ssl/ + + <p>前言 什么是SSL/TLS证书?它有什么作用?如何部署?</p> + + + + Network的艺术:国内至国际骨干ISP线路整理 + 2024-02-10T00:00:00+00:00 + 2024-02-10T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/network-isps/ + + <p>前言 本文主要探讨的是IPv4网络,国际出口线路的质量分析以及各大ISP的介绍。</p> + + + + Network的艺术:下载技术的历史 + 2024-02-09T00:00:00+00:00 + 2024-02-09T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/network-download-1/ + + <p>前言 下载,就是将我们所需要的文件数据,通过网络从拥有该文件资源的计算机上传输过来并保存到我们的计算机上,供我们使用。本系列将详细讲述各种常见网络下载技术的原理,包括HTTP,FTP,BT等等。</p> + + + + 乱七八糟:Git使用简明手册 + 2023-12-15T00:00:00+00:00 + 2023-12-15T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-git/ + + <p>前言 Git,作为现代软件开发中不可或缺的版本控制工具,常常让初学者感到困惑。本文旨在介绍 Git 的全流程安装和基本使用,希望能够帮助新手更轻松地理解和掌握 Git 的基本概念和操作。</p> + + + + 乱七八糟:垃圾清理的艺术 + 2023-11-19T00:00:00+00:00 + 2023-11-19T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-junk-cleanup/ + + <p>前言 在从前的机械硬盘时代,由于硬盘空间小,且没有时常清理垃圾文件,常常导致硬盘空间严重不足;特别是在以 Windows 平台为代表的 C/D盘 体系下。那么,我们常说的垃圾清理,释放硬盘空间,到底是在清理什么?哪些文件可以被清理?</p> + + + + 乱七八糟:个人博客搭建 + 2023-10-12T00:00:00+00:00 + 2023-10-12T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-blog/ + + <p>前言 个人博客的搭建具有许多的方案可以选择,本文介绍如何快速部署一个博客,并将其发布到公网。</p> + + + + 乱七八糟:机械革命键盘失灵拯救记 + 2023-09-04T00:00:00+00:00 + 2023-09-04T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-mechrev-keyboard/ + + <p>前言 机械革命作为一款极高性价比的笔记本,其优惠的力度和问题不断的故障让玩家们爱恨交织;作者在其上安装 Linux 时遇到了键盘失灵的问题,为了避免更多人踩坑,故写本文。</p> + + + + 乱七八糟:常见发音错误术语集合 + 2023-08-25T00:00:00+00:00 + 2023-08-25T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-accurate-pronunciation/ + + <p>前言 中文和英语发音习惯不同,容易引起误解。本文旨在帮助您准确发音常见的科技术语,欢迎随时补充。</p> + + + + 乱七八糟:流量卡购买与套路 + 2023-08-24T00:00:00+00:00 + 2023-08-24T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/about-calling-cards/ + + <p>前言 由于临近升学,校园网不尽人意,因此许多小伙伴有了买一张流量卡的计划。本文以三大运营商为例,说明常见流量卡的套路与选择。</p> + + + + 综合工程:Arch-linux 安装与配置 + 2023-08-16T00:00:00+00:00 + 2023-08-16T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/awesome-arch-linux/ + + <p>前言 Arch linux是一个轻量、灵活、滚动更新的 Linux 发行版,衍生了诸多优秀的桌面端linux。其官方Wiki更是被称为技术界的“武林秘籍”;这里介绍其安装与使用。</p> + + + + 综合工程:Android-TV 折腾小记 + 2023-08-14T00:00:00+00:00 + 2023-08-14T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/awesome-android-tv/ + + <p>前言 由于 AppleTV 的高昂的售价和普通电视盒子广告的泛滥,一台开源、多功能的原生安卓电视盒子逐渐成为智能家居的必备神器。出于对 IPTV、YouTube 和家庭影院等需求,以及对一面赏心悦目电视墙的期待,这里分享 Android TV (以下简称ATV)安装的一些要点。</p> + + + + 综合工程:安卓刷机与root教程 + 2023-08-13T00:00:00+00:00 + 2023-08-13T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/awesome-android-root/ + + <p>前言 自安卓系统诞生以来,root 一直是玩机的必备过程。时至今日,在安卓定制系统日益完善的情况下,能 root 的机型越来越少,本文以小米手机为例,介绍 root 的具体方法。</p> + + + + 综合工程:OpenWrt路由部署与软件编译 + 2023-08-12T00:00:00+00:00 + 2023-08-12T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/awesome-openwrt/ + + <p>前言 openwrt 是一个自由的、兼容性好的嵌入式 linux 发行版。作为软路由玩家必备的一款神器,可以实现诸如去广告,多拨和科学上网等多种功能。本文介绍openwrt在各种平台上的部署流程。</p> + + + + 综合工程:PVE安装与MC服务器搭建 + 2023-08-11T00:00:00+00:00 + 2023-08-11T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/awesome-pve-mcsm/ + + <p>前言 假期将至,不少家里有闲置设备的小伙伴想尝试开设一个我的世界(Minecraft)服务器,却不知从何下手。本文以 PVE-Debian-MCSM 为主线介绍其部署流程。</p> + + + + 综合工程:linux搭建安卓虚拟机 + 2023-08-10T00:00:00+00:00 + 2023-08-10T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/awesome-vm-android/ + + <p>前言 linux搭建安卓虚拟机有Waydroid,QEMU和Docker三种方案,各有不同。</p> + + + + Linux之旅(七):系统与终端字体设置 + 2023-08-01T00:00:00+00:00 + 2023-08-01T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/learn-linux-for-pc-7/ + + <p>前言 一个好看的字体会提高工作效率与审美.Linux 下的字体可以很漂亮,但需要一些设置.</p> + + + + Linux之旅(六):常用命令与性能分析 + 2023-07-25T00:00:00+00:00 + 2023-07-25T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/learn-linux-for-pc-6/ + + <p>前言 在学习Linux操作系统时,熟悉常用命令和性能分析工具是至关重要的。让我们一起探索Linux的世界,提升技能,解锁无限可能!</p> + + + + Linux之旅(五):BIOS-UEFI-MBR-GPT-GRUB + 2023-07-24T00:00:00+00:00 + 2023-07-24T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/learn-linux-for-pc-5/ + + <p>前言 在计算机领域,系统引导和磁盘分区是至关重要的。本文将介绍BIOS与UEFI,MBR与GPT,以及它们之间的异同点。此外,我们还会讨论与这些概念密切相关的引导加载程序——GRUB。</p> + + + + Linux之旅(四):Terminal,Console and Shell + 2023-07-23T00:00:00+00:00 + 2023-07-23T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/learn-linux-for-pc-4/ + + <p>前言 在linux的学习过程中,我们常常遇到诸如 Terminal,Console,bash,zsh,shell,tty 等概念,这些概念常常被混淆,似乎都和命令行相关。本文从历史角度出发介绍它们的前世今生。</p> + + + + Linux之旅(三):内核/shell/包管理/文件系统/桌面环境 + 2023-07-22T00:00:00+00:00 + 2023-07-22T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/learn-linux-for-pc-3/ + + <p>前言 在Linux世界中,内核/shell/包管理/文件系统构成了Linux系统的核心,它们相互配合,共同构建了一个强大而稳定的操作环境。本文将深入探讨这些关键组成部分,解释它们的作用和原理,帮助读者更好地理解Linux系统的运作机制。</p> + + + + Linux之旅(二):FHS与目录结构 + 2023-07-21T00:00:00+00:00 + 2023-07-21T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/learn-linux-for-pc-2/ + + <p>前言 在Linux世界中,Filesystem Hierarchy Standard(FHS)是一座引导我们进入系统核心的桥梁,它定义了Linux系统中目录结构的规范与作用,为我们提供了一张清晰的地图,指引我们轻松管理和理解系统。本文将深入探讨FHS规范与Linux系统目录结构,解释各个目录的用途与功能,帮助我们更好地理解和利用Linux系统。</p> + + + + Linux之旅(一):构成与发行版 + 2023-07-20T00:00:00+00:00 + 2023-07-20T00:00:00+00:00 + + + + + Unknown + + + + + + https://blog.dich.bid/learn-linux-for-pc-1/ + + <p>前言 Linux 作为一款强大、灵活且免费的操作系统,吸引了越来越多的用户。然而,对于初学者来说,Linux 可能显得有些陌生,甚至有些令人望而生畏。本文旨在为那些刚踏入 Linux 世界的新手提供一份指南,帮助他们更好地了解、使用这个令人着迷的操作系统。我们将探讨Linux的基本概念,解释为何选择Linux,深入剖析其主要构成要素以及不同的发行版之间的差异。</p> + + + \ No newline at end of file diff --git a/public/awesome-android-root/index.html b/public/awesome-android-root/index.html new file mode 100644 index 0000000..d5f1858 --- /dev/null +++ b/public/awesome-android-root/index.html @@ -0,0 +1,405 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

综合工程:安卓刷机与root教程

+ + + + + + +
+

前言 自安卓系统诞生以来,root 一直是玩机的必备过程。时至今日,在安卓定制系统日益完善的情况下,能 root 的机型越来越少,本文以小米手机为例,介绍 root 的具体方法。

+

一.什么是root

+

这涉及安卓的权限系统。Andoird 系统是基于 Linux 内核的,Linux中的root用户为超级用户,root 权限则为系统的最高权限,与 Windows 的 system 权限相当(比 administer 还高)。日常使用中我们可以发现一般软件权限需要经过用户同意,即每次安装前出现的各种请求弹窗。我们看似可以做到许多事情,但有些地方比如安卓的根目录没有root就无法查看。

+

所谓 Root 也就是使手机获得超级管理员的权限,但是出于种种原因,厂商默认不提供超级管理员的权限,因此,root的本质就是一个提权的过程

+

二.为什么要root

+
    +
  1. +

    国内定制的安卓系统充满着云控,反诈以及各种广告,预装软件,这种系统实在为极客们所不容;而当我们具备了 root 权限后,就可以实现许多功能,例如屏蔽广告,虚拟定位,安装 Google 框架和软件,满血运行CPU,删除系统自带软件等等。

    +
  2. +
  3. +

    某种意义上不能root的手机相当于只有使用权而无所有权,不能完全控制自己的数据。

    +
  4. +
  5. +

    我可以不要但你厂商不能不给。

    +
  6. +
+
+

云控:一般指为了计划性报废而特地远程操控使用户的手机变的卡顿,加快换机;也有另一层含义:在UP主测试手机时调整设置使其跑分虚高而用户到手的手机分数远不如测试的时候的情况。

+
+
+

反诈:一般指厂商与网络安全部门合作的后门或漏洞,可以监控用户行为,例如某 +“其他”品牌手机系统的webview级别的网址拦截;

+
+
+

广告:一般指系统自带的弹窗广告,自带系统应用中的广告和“负一屏”中的广告。

+
+

三.哪些机型可以root

+

在 2023 年的今天,能 root 的机型还是比较少。各品牌手机root情况汇总

+ + + + + + + + + + + + + + + + + + +
品牌 / 机型BL 解锁情况等待时长支持回锁Root/越狱 能力
OnePlus✅ 支持秒解✅ 支持✅ 容易 root
Google (Pixel)✅ 支持秒解✅ 支持✅ 容易 root
Nothing Phoneℹ️ 社区支持✅ 社区方法多
Motorola✅ 支持官方发解锁码⚠️ 部分✅ 社区方法多
Xiaomi/Redmi/POCO⚠️ 支持~7–14 天⏹ 部分✅ 可 root(需等待)
Lenovo✅ 支持秒解⚠️ 部分✅ 容易 root
Sony⚠️ 支持⚠️ 部分✅ 海外版易 root
OPPO / Realme⚠️ 支持❌ 部分型号难 root
Vivo / iQOO⚠️ 支持❌ 部分型号难 root
Huawei❌ 不支持❌ 基本不可 root
Honor❌ 不支持⚠️ 少数型号有社区支持
ASUS❌ 不支持❌ 不可 root
Black Shark❌ 不支持❌ 不可 root
LG❌ 不支持✅ 支持⚠️ 旧机型可能可 root
Meizu❌ 不支持⚠️ 部分机型有 root 方法
Samsung⚠️ 支持❌ 解锁后 Knox 熔断,Pay 功能被禁用
Apple iPhone❌ 不支持✅ iPhone 10 前可越狱
+

刷机有风险,root 需谨慎!刷机前要了解相应的厂商,考虑保修和变砖的问题!

+

四.确定你要刷的系统

+

可以选择官方原版,官改版,海外版和类原生版。官方原版镜像一般用来救砖;官改版在一些方面例如性能更为强大;海外版本如EEA(欧盟版)为符合法规对隐私保护更好且广告更少;而类原生版是在AOSP的基础上进行简单修改,最为纯净原生。

+

需要注意这些rom的搜索往往使用的海外名,得先搜索你所对应机型的海外名称/代号。

+ +
+

需要注意的是刷类原生系统较之其他系统可能会有如下问题;如果你只需要root,推荐使用原厂系统。

+
+
    +
  • 解锁BL之后Tee假死,无法使用指纹付款;
  • +
  • 由于原厂相机驱动不开源,相机变的模糊;
  • +
  • 部分机型无法快充;
  • +
  • 12306无法使用前置人脸识别;
  • +
  • 5G可能无法使用;
  • +
+

五.如何root

+

首先我们要了解安卓系统的分区和启动。安卓的分区包括:

+
    +
  • +

    recovery 分区,类似PC端的PE环境,手机上的恢复出厂设置即为从 recovery 恢复;

    +
  • +
  • +

    cache 分区,保存系统最常访问的数据和应用程序。 擦除这个分区,不会影响个人数据,只是删除了这个分区中已经保存的缓存内容;

    +
  • +
  • +

    boot 分区,类似PC端的MBR分区,用来引导系统启动,擦除后手机会卡在开机 logo 的界面;

    +
  • +
  • +

    system 分区,包括操作系统与软件,vendor 定制文件与库文件等等,擦除后会卡在开机的动画界面;

    +
  • +
  • +

    data 分区,存放用户数据和系统设置,擦除后不影响系统的运行。

    +
  • +
+
+

除了以上5大分区外,手机启动阶段还存在名为 bootloader 的程序,通常位于设备的专用引导区域(如boot ROM或firmware分区的一部分),与 PC 端的 BIOS 类似,被称为 fastboot 模式,厂商一般会将其锁定,要刷机的话必须解开它。

+
+
+

早些年间,存在大量一键 root,kingroot 之类的软件,可以直接刷写 root 包,获得 root 权限,但成功率不高,且有植入木马之嫌。

+
+

因此,现在主流的刷机步骤

+
    +
  • +

    备份手机数据,即备份Data分区(可使用Neobackup或系统自带),字库/基带/官方固件,桌面样式截图以及该机器的官方原厂包;

    +
  • +
  • +

    打开机器上的允许USB调试;

    +
  • +
  • +

    解开 bootloader,俗称解BL锁. BL锁原理参考

    +
  • +
  • +

    下载要刷的第三方系统包和原厂系统包并提取以上两个包中的 boot.img 和 recovery.img 文件;

    +
  • +
  • +

    将机器与PC等设备连接,并进入 bootloader;

    +
  • +
  • +

    刷入第三方 recovery,比如大名鼎鼎的 TWRP,或者对应新系统的recovery.img;

    +
  • +
  • +

    进入 recovery 模式,清空原系统数据并刷入新系统Zip包,随后重启,即可进入新系统。

    +
  • +
+

主流的root步骤:

+
    +
  • Magisk:在recovery中刷入 Magisk (面具)zip包,随后重启进入桌面,安装 Magisk(apk),在其中选择直接安装;
  • +
  • Apatch:安装apk软件并修补提取出来的boot.img,随后在fastboot模式中fastboot flash boot apatch_patched-boot.img,重启即可。
  • +
  • KernelSU:修补init_boot.img或者刷入GKI内核修补,若官方无支持需要自行编译GKI内核。
  • +
+

常用root方案

+ +

六.具体操作流程

+
+

前置知识:ADB与Fastboot命令的使用

+
+

adb 命令

+ + + + + + + +
命令说明
adb devices列出 adb 设备
adb reboot重启设备
adb reboot bootloader重启到 fastboot 模式
adb reboot recovery重启到 recovery 模式
adb reboot edl重启到 edl 模式
adb sideload <要刷写的文件路径>刷写模块,如 Magisk
+

fastboot 命令

+ + + + + + + +
命令说明
fastboot devices列出 fastboot 设备
fastboot reboot重启设备
fastboot reboot-bootloader重启到 fastboot 模式
fastboot flash <分区名称> <镜像文件名>刷写分区
fastboot oem reboot-<模式名称>重启到相应模式
fastboot oem device-info查看解锁状态
+
+

以 Poco F2 这款手机为例,

+
+
    +
  1. +

    首先我们进入手机设置界面,进入“我的设备”,在“全部参数”中找到“ MIUI 版本”,连续点击后开启开发者模式,随后在“更多设置”中开启 USB 调试, USB安装 功能。

    +
  2. +
  3. +

    然后我们进入小米官网 ,下载官方解锁工具,需要登陆小米账号并等待7天,随后即可解锁。

    +
  4. +
  5. +

    解锁完成后在MiFirm网 中下载对应的 TWRP 版本。

    +
  6. +
  7. +

    随后用数据线连接手机,用其中的一键刷写刷入 TWRP;随后下载你要刷的系统的 rom 包,下载时注意一并下载 boot.img 文件,作为 Magisk 的修补用。然后下载 Magisk 包,与 rom 一起存入TF卡或者U盘中。

    +
  8. +
+
+

注意,由于本机型为新型AB分区因此如果刷机失败,需要下载原厂包用以恢复AB分区,否则无法启动和安装rom。

+
+
    +
  1. +

    进入 recovery 模式,首先我们清除Data、Cache两个分区,俗称“双清”,随后在高级清除选项中清除 Data、Cache、Dalvik Cache 和 System 分区,俗称“四清”。

    +
  2. +
  3. +

    清除完成后即可开始刷机。将 TF 卡或者U盘插入手机,在“安装”中选择 rom 包,右滑确认刷机;随后如法炮制,刷入 magisk.zip 包,不然会卡在开机 logo 界面,俗称“卡米”。

    +
  4. +
  5. +

    刷完之后重启,则会进入安装界面。注意:如果刷的是海外版的包,千万不能联网安装,否则会失败且变为国内版。

    +
  6. +
  7. +

    此刻我们将下载好的 boot.img 文件复制到手机上,打开 Magisk 软件,在其中选择修补一个文件,选中 boot.img,修复完成后可以看到超级用户一栏可以使用了,说明 root 完成。

    +
  8. +
+
+

以一加(oneplus)为例:

+
+
    +
  1. +

    打开开发者模式并开启USB调试,连接到提前装好ADB/Fastboot驱动的电脑;

    +
  2. +
  3. +

    随后进入fastboot模式(adb reboot bootloader),执行fastboot oem unlock或者fastboot flashing unlock,查看fastboot oem device-info,若为Device unlocked: true表示已成功解锁。

    +
  4. +
  5. +

    随后刷入新系统的recovery.img,使用命令fastboot flash recovery xxx.img;四清操作可以用fastboot erase data / fastboot erase cache / fastboot erase system / fastboot erase metadata 代替。

    +
  6. +
  7. +

    随后进入新系统的recovery,使用命令fastboot reboot recovery,在其中adb sideload xxx.zip,即为刷入新系统的全量包。

    +
  8. +
  9. +

    随后 adb reboot 即可进入新系统。

    +
  10. +
+
+

如果你不想安装TWRP也可以直接安装要刷的系统的recovery,一般放在系统zip包的中,如果没有则需要手动解包payload.bin,可以安装payload-dumper-go并在解压出来的系统文件夹中使用payload-dumper-go payload.bin,随后会将所有.img后缀的文件放在文件夹中。

+
+

八.Root后的模块安装

+

在 Root 管理器中安装 Zygisk-Lsposed 模块,即可使用 Lsposed,在 Lsposed 中可以安装 HMA, Amarok ,QAuxiliary 模块,并配合 MMRL 等软件等等。

+
+

免 Root 的平替方法,目前这一套流程也很成熟了:利用 ADB 权限的 Shizuku;利用 Device Owner 权限的 Dhizuku等等。

+
+
+

常用模块

+
+ +

参考

+ + +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/awesome-android-tv/index.html b/public/awesome-android-tv/index.html new file mode 100644 index 0000000..429ebbb --- /dev/null +++ b/public/awesome-android-tv/index.html @@ -0,0 +1,316 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

综合工程:Android-TV 折腾小记

+ + + + + + +
+

前言 由于 AppleTV 的高昂的售价和普通电视盒子广告的泛滥,一台开源、多功能的原生安卓电视盒子逐渐成为智能家居的必备神器。出于对 IPTV、YouTube 和家庭影院等需求,以及对一面赏心悦目电视墙的期待,这里分享 Android TV (以下简称ATV)安装的一些要点。

+

零.要实现的目标

+
    +
  • 实现自己的设备(X86/Arm)上安装TV系统;
  • +
  • 实现无开机广告和内置广告
  • +
  • 实现海报墙效果(矩形磁帖),或自定义安卓桌面启动器;
  • +
  • 实现影视番剧观看,基于TVbox/Kodi/Kazumi;
  • +
  • 实现国内流媒体观看,包括Bilibili,爱优腾等等;
  • +
  • 实现国外流媒体观看,包括Netflix,YouTube,Disney+,Spotify等等;
  • +
  • 实现家庭影院,Emby类软件自动刮削;
  • +
  • 实现IPTV观看,采用自抓取源或者公共源;
  • +
  • 实现复古游戏游玩,包括GBA/FC等等,基于RetroArch/PPSSPP/Emuelec,可以连接手柄;
  • +
  • 实现游戏主机串流,包括PS/Xbox/Switch等等;
  • +
+

一.选择合适的平台

+

X86还是Arm?两者之间各有优点,截止到今天各种Arm电视盒子已经非常成熟,价格便宜,也可以使用运营商的电视盒子进行刷机,性能并不会太弱;而X86平台往往价格偏贵,且解码性能和功能适配没有和电视生态联系紧密,因此建议首选Arm平台。

+

二.选择合适的系统

+

无论是运营商自带的电视盒子还是各种所谓的“无广告”电视盒子,往往都基于以下两种系统,且不要迷信所谓的“无广告”电视盒子,它们往往配置低下,性价比不高且还是有内置付费项目,甚至有一些根本没有做到去广告。

+ + + + + + + + + + + +
特性Android-x86Android TV
目标用户面向 PC 用户,将 Android 运行在 x86/x86_64 设备上。面向电视和机顶盒用户,优化用于遥控器或语音操作。
适配设备传统 PC、笔记本、平板电脑等 x86 架构设备。智能电视、电视盒子等 ARM 或特定芯片架构设备。
界面设计和标准 Android 类似,为触摸屏和鼠标键盘优化。专为大屏设计,使用 Leanback UI,适配遥控器操作。
Google 服务默认不包含 Google 服务,需要用户手动安装。官方版本内置 Google 服务(例如 Play Store、Assistant)。
开机启动器使用标准 Android 桌面启动器(Launcher3)。使用电视优化的启动器(Leanback Launcher)。
架构支持专注于 x86/x86_64,但支持 ARM 仿真(通过 Houdini)。主要支持 ARM/ARM64 架构,有限支持 x86。
硬件支持需要额外优化,部分硬件(如 GPU 驱动)可能无法正常工作。深度集成硬件,默认支持电视硬件(如 HDMI CEC、音频输出)。
应用市场默认不内置 Google Play,需要手动安装 Aurora Store 等替代方案。默认集成 Google Play 商店,提供大屏优化的应用程序。
遥控器支持不适配遥控器,主要使用鼠标键盘操作。专为遥控器优化,支持按键导航和语音输入。
开源贡献由社区维护,支持各种自定义和实验功能。由 Google 官方主导,OEM 厂商提供硬件优化支持。
+
+
+

Android-x86 的安装类似windows,需要命令行界面配置;Android TV安装类似 Android手机,通过刷分区或TWRP卡刷安装。

+
+
+

Tosathony 制作的 Android TV x86 是一个由社区成员制作的定制化 Android TV 版本,针对 Android TV 的大屏界面 和 遥控器操作 进行特别优化,但某些硬件(如 Wi-Fi、GPU、音频设备等)的驱动可能不兼容或需要额外的配置。

+
+

刷 Tosathony Android TV X86 准备工作

+ +

一些可安装的软件

+ +

一、写盘,BIOS启动

+
    +
  • +

    使用 Rufus 将下载好的 ATV 镜像写入U盘。

    +
  • +
  • +

    将U盘插到目标主机上,并设置 BIOS-boot 优先启动,不同设备进入 BIOS 的按键不同,大部分是F2或者DEL;

    +
  • +
+

二、开始安装

+
    +
  • +

    boot 成功后选择自动安装;

    +
  • +
  • +

    经过跑码后进入若干个选项,一路 yes 过去,文件系统选 ext4;随后运行 ATV ,并拔出U盘;

    +
  • +
+

三、进入Google界面

+

由于国内网络环境问题,导致一些界面无法进入,可使用如下方法或全局科学。

+

1.如果卡在 Google的logo 界面或者动画比较缓慢,或者重启后无法进入 ATV 界面,需要在BIOS-Advanced-OS selection中将其设置为Windows 8.X或者Android。

+

2.然后可以看到 PayPal 界面,这里使用可以 Ctrl+Alt+F1 进入命令行界面,随后输入

+

pm disable com.tosanthony.tv.networkprovider #注意空格

+

回车执行,随后按Ctrl+Alt+F7或F8回到图形界面。

+

3.下一步,我们可以看到自动更新界面,这里我们需要禁用它:

+

同样Ctrl+Alt+F1 进入命令行界面,随后输入

+

pm disable com.google.android.tungsten.setupwraith #注意空格

+

回车执行,随后按Ctrl+Alt+F7或F8回到图形界面。

+

4.此时会进入一个 WiFi 界面,如果你是使用网线直连就没有问题,或者用键盘连接家里的WiFi,作者因为工控机没有WiFi模块在这里卡了半天。

+

5.随后进入了 AndroidTV 的桌面。

+

四、安装软件并设置桌面启动

+

1.首先我们在设置中找到“设置”>“设备首选项”>“关于”,然后在“构建”上点击几次以解锁“开发人员”选项,随后开启USB调试开关。

+

2.随后在设置 > 设备首选项 > 关于 > 状态中找到并记下IP 地址,然后用Tiny ADB连接上去,这里使用命令adb connect <IP 地址> ,随后在ATV端授权连接;

+

3.接着使用命令adb install 将要安装的软件包上传,也可以将文件拖到命令提示符窗口上以复制其路径,回车确认。

+

一些 ADB 常用命令

+
adb reboot #将重启 Android 设备。
+
+adb reboot recovery #将设备重新启动到恢复模式。
+
+adb push <local> <remote> #将文件从您的 PC 复制到您的 Android 设备。
+
+adb shell wm density <dpi> #改变显示器的像素密度。
+
+adb kill server #切断 PC 和 Android TV 之间的连接。
+
+

4.如果存在一些软件无法安装,可开启ARM兼容层,具体方法为在 dl.android-x86.org/houdini/9_y/houdini.sfs 中下载得到houdini.sfs,把文件名改成houdini9_y.sfs,随后拷贝进U盘,进入命令行界面,输入 ls 找到 storage 目录,输入 cd storage 进入你的U盘,输入 ls ,查看你拷贝的 houdini9_y.sfs 文件,并复制到该目录下。

+
cp houdini9_y.sfs /system/etc
+
+enable_nativebridge
+
+reboot
+
+

5.安装一些软件包后我们发现需要代替掉ATV自带的桌面,从而形成海报墙的效果,这和 linux 的桌面环境切换有异曲同工之处。注意:替换前需要已经安装完成其他桌面!!!!(比如 ATV Launcher )我们使用以下命令禁用 google 默认的桌面。随后重启,即可看到ATV的海报墙。

+

pm disable-user --user 0 com.google.android.tvlauncher

+

恢复原有桌面:

+
C:\Users\root>adb shell
+generic_x86:/ $ su
+generic_x86:/ # pm enable --user 0 com.google.android.tvlauncher
+Package com.google.android.tvlauncher new state: enabled
+
+

后记

+ + +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/awesome-arch-linux/index.html b/public/awesome-arch-linux/index.html new file mode 100644 index 0000000..3d6e429 --- /dev/null +++ b/public/awesome-arch-linux/index.html @@ -0,0 +1,447 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

综合工程:Arch-linux 安装与配置

+ + + + + + +
+

前言 Arch linux是一个轻量、灵活、滚动更新的 Linux 发行版,衍生了诸多优秀的桌面端linux。其官方Wiki更是被称为技术界的“武林秘籍”;这里介绍其安装与使用。

+

安装

+

一般而言有以下几种安装方法:

+
    +
  • 原版 Arch linux 的命令行安装;
  • +
  • 原版 Arch linux 的脚本安装;
  • +
  • 第三方发行版的图形界面安装。
  • +
+

前两种方法较为繁琐,这里说明第三种方法:常见的Arch发行版有Garuda,Cachyos以及EndeavourOS等等。

+ +

安装方法同ubuntu一样,是基于Calamares的图形化界面安装。一般步骤为选择语言(American English)--选择键盘/时区(默认/shanghai)--选择分区(xfs抹除全盘,可选全盘加密)--选择桌面环境(Gnome或KDE)--确认安装。

+

安装软件

+

随后安装常用开源软件:

+
# gui
+
+paru -S alacritty zellij qemu-full virt-manager wireshark-qt floorp-bin foliate materialgram-bin legcord-bin keepassxc onlyoffice-bin kazumi-bin vlc krita qtscrcpy localsend-bin strawberry oculante obs-studio
+
+# tui
+
+paru -S neovim yazi lazygit btop
+
+# cli
+
+paru -S nexttrace-bin android-tools syncthing aria2 zola fastfetch onefetch starship atuin bat fzf eza tree
+
+# other
+
+paru -S ttf-jetbrains-mono-nerd fcitx5-chinese-addons  fcitx5-skin-material fcitx5-im fcitx5-rime npm pnpm just go wl-clipboard
+
+

安装完毕后我们开始配置输入法与字体:

+

输入法我们采用雾凇拼音,即前面我们安装的fcitx5系列软件包的一个输入方案,这里我们使用自动部署脚本

+
# step1: 克隆/下载 latest 最新的稳定版到本地
+git clone --depth=1 https://github.com/Mark24Code/rime-auto-deploy.git --branch latest
+# step2: 进入项目目录
+cd rime-auto-deploy
+# step3: 执行部署脚本
+./installer.rb
+
+

选择部署fcitx5即可,随后在设置的Input Method中Add Input Method ,选择Rime,随后默认按Ctrl+Space即可切换中文。

+

字体的配置在Linux之旅(七):系统与终端字体设置这一期说过,这里不再赘述。缺少的字体可以通过paru下载或者到喵闪字库下载ttf并安装。

+

图形美化

+

安装完毕后可以看到KDE的界面较为简陋,这里给出笔者的美化配置:

+
    +
  • 在设置中找到Colors&Themes,分别设置为:
  • +
+
- Color:Breeze Dark
+- Application Style:Breeze
+- Plasma Style:Sweet
+- Window Decorations:Edna
+- Icons:BeautySolar
+- Cursors:Afterglow Cursors
+- Splash Screen:None
+
+
    +
  • +

    随后设置壁纸,这里给出了笔者收藏的壁纸

    +
  • +
  • +

    设置完成后将Dock栏的Status全部隐藏,删除间隔与空隙,删除时间,更改Memu图标,随后固定常用软件到其上。

    +
  • +
  • +

    随后在Dock栏下新建一个空白栏,结构为数字时钟加两个空白,字体为JetBrains Mono,24小时ISO格式。最终效果如下:

    +
  • +
+

desktop

+

迁移数据

+

将需要的数据迁移到Home目录下,对笔者来说是用来同步的Data文件夹以及Git工作文件夹。随后Add to Places将其固定到侧边栏,开启隐藏文件可见,将View mode改为Detail。最终效果如下:

+

file

+

设置软件

+
    +
  • 配置fastfetch显示效果
  • +
+
创建配置目录:mkdir -p ~/.config/fastfetch
+创建配置文件:touch ~/.config/fastfetch/config.jsonc
+编辑该文件以添加你的自定义选项
+
+
    +
  • +

    设置GFS:参考乱七八糟:GFS项目考量笔记

    +
  • +
  • +

    设置Keepassxc/Vscodium/Electerm:导入备份好的配置文件。

    +
  • +
  • +

    设置Matrix/Telegram:登录并在另一台设备上验证。

    +
  • +
  • +

    设置浏览器:导入书签备份文件(有图标);定制工具栏,下载扩展插件,包括:

    +
  • +
+
Dark Reader(暗黑模式)
+kiss-translator(翻译工具)
+uBlock Origin(广告拦截)
+ClearURLs(去跟踪链接)
+KeePassXC-Browser(链接Keepass)
+BookmarkHub(书签同步)
+BewlyBewly(B站美化)
+V2EX Polish(V站美化)
+
+

双系统添加Windows引导

+

如果Grub引导菜单中没有windows选项,可以通过以下方法添加:

+
    +
  • 安装 os-prober:首先确保系统中安装了 os-prober,这是一个用于检测其他操作系统的工具。
  • +
+
sudo pacman -S os-prober
+sudo os-prober
+
+
    +
  • 打开 /etc/default/grub 文件进行编辑:
  • +
+
sudo nano /etc/default/grub
+# 确保 GRUB_DISABLE_OS_PROBER 设置为 false
+
+
    +
  • 保存文件并退出编辑器后,运行以下命令更新 GRUB 配置:
  • +
+
sudo grub-mkconfig -o /boot/grub/grub.cfg
+
+

或者手动添加

+
nano /etc/grub.d/40_custom
+
+
#!/bin/sh
+exec tail -n +3 $0
+# This file provides an easy way to add custom menu entries.  Simply type the
+# menu entries you want to add after this comment.  Be careful not to change
+# the 'exec tail' line above.
+menuentry "Windows 11 (Manual)" {
+    insmod part_gpt
+    insmod fat
+    insmod chain
+    set root='hd0,gpt1'
+    chainloader /EFI/Microsoft/Boot/bootmgfw.efi
+}
+
+

Arch中安装QEMU虚拟机

+

前面我们已经安装了Qemu高性能虚拟机平台和virt-manager用来管理虚拟机的图形界面,随后配置virt-manager并安装Ubuntu-server:

+

如果virt-manager报错无法找到Qemu,则:

+
    +
  • ​如果 libvirtd 服务未运行,virt-manager 将无法连接到虚拟化环境。​
  • +
+
sudo systemctl start libvirtd
+sudo systemctl enable libvirtd
+
+
    +
  • 用户权限问题:​​将当前用户添加到 libvirt 组,以获得必要的权限。​
  • +
+
sudo usermod -aG libvirt $(whoami)
+
+
    +
  • 虚拟网络未激活:​virt-manager 可能无法连接到默认的虚拟网络。​
  • +
+
sudo virsh net-start default
+
+

默认网络在系统启动时自动启动,可以执行:

+
sudo virsh net-autostart default
+
+
    +
  • 配置文件权限问题:​配置文件的权限设置可能导致访问问题。
  • +
+
sudo chown $(whoami):libvirt /var/run/libvirt/libvirt-sock
+
+

随后安装虚拟机,流程大概为选择镜像和系统类型--设置CPU/内存--设置空间大小--编辑配置项--开启UEFI引导和3D加速.

+

开启3D加速:

+
    +
  • NIC:
  • +
+
<graphics type="spice">
+  <listen type="none"/>
+  <image compression="off"/>
+  <gl enable="yes" rendernode="/dev/dri/by-path/pci-0000:05:00.0-render"/>
+</graphics>
+
+
+
    +
  • video virtio:
  • +
+
<video>
+  <model type="virtio" heads="1" primary="yes">
+    <acceleration accel3d="yes"/>
+  </model>
+  <alias name="video0"/>
+  <address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0"/>
+</video>
+
+

安装完成后即可使用electerm进行SSH连接,如果无法连接,可以将Tun模式开启的"strict_route"关闭。

+

更改启动内核顺序

+

如果安装了多个linux内核,可以使用以下方法调整启动顺序:

+
    +
  • 使用以下命令查看内核名称:
  • +
+
ls /boot/vmlinuz*
+
+
    +
  • 在 /etc/default/grub 中添加或修改如下行:
  • +
+
GRUB_TOP_LEVEL="/boot/vmlinuz-linux-cachyos"
+
+

需要注意,这种方法会关闭 GRUB 的“记住上次启动项”的功能。

+
    +
  • 修改完 /etc/default/grub 后,记得重新生成 GRUB 配置文件:
  • +
+
sudo grub-mkconfig -o /boot/grub/grub.cfg
+
+

图形界面更改方法:

+

可以使用grub-customizer来修改Grub,这里以ubuntu为例子:

+
    +
  • 添加PPA源并更新软件列表:
  • +
+
sudo add-apt-repository ppa:danielrichter2007/grub-customizer
+sudo apt update
+
+
    +
  • 安装GRUB Customizer:
  • +
+
sudo apt install grub-customizer
+
+

随后在grub-customizer中将要默认启动的选项放在首位即可。

+

开机自启动

+

设置Syncthing开机自启动

+
sudo systemctl enable --now syncthing@<username>.service
+
+

开启BBR

+
    +
  • 确保你的内核版本 >= 4.9:
  • +
+
uname -r
+
+
    +
  • 启用 BBR
  • +
+

你只需要设置两个 sysctl 参数即可:

+
sudo sysctl -w net.core.default_qdisc=fq
+sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
+
+

要让它们永久生效,把它们写入配置文件:

+
sudo nano /etc/sysctl.d/99-bbr.conf
+
+

加入以下内容:

+
net.core.default_qdisc = fq
+net.ipv4.tcp_congestion_control = bbr
+
+

然后重新加载配置:

+
sudo sysctl --system
+
+
    +
  • 验证 BBR 是否启用
  • +
+
sysctl net.ipv4.tcp_congestion_control
+
+

应该输出:

+
net.ipv4.tcp_congestion_control = bbr
+
+

在Arch Linux上安装Docker

+

一般推荐在qemu虚拟机中安装,这里仅做示例:

+
sudo pacman -S docker
+
+

安装完成后,需要启动Docker服务,并设置为开机自启:

+
sudo systemctl start docker
+sudo systemctl enable docker
+
+

运行以下命令来验证Docker是否正常工作:

+
sudo docker run hello-world
+
+

默认情况下,只有root用户才能运行Docker命令。为了避免每次运行Docker命令时都需要使用sudo,可以将当前用户添加到docker组:

+
sudo usermod -aG docker $USER
+
+

之后,需要注销并重新登录,或者重启系统以使更改生效。

+

安装Docker Compose:

+
sudo pacman -S docker-compose
+
+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/awesome-openwrt/index.html b/public/awesome-openwrt/index.html new file mode 100644 index 0000000..f7792db --- /dev/null +++ b/public/awesome-openwrt/index.html @@ -0,0 +1,717 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

综合工程:OpenWrt路由部署与软件编译

+ + + + + + +
+

前言 openwrt 是一个自由的、兼容性好的嵌入式 linux 发行版。作为软路由玩家必备的一款神器,可以实现诸如去广告,多拨和科学上网等多种功能。本文介绍openwrt在各种平台上的部署流程。

+

要实现的目标

+
    +
  • 1.IPv6 分配到每个设备;
  • +
  • 2.NAT类型为NAT1(全锥形);
  • +
  • 3.可控的流量记录与IP控制/QOS;
  • +
  • 4.可靠的硬件加速;
  • +
  • 5.多线多播/宽带提速;
  • +
  • 6.PPPoE拨号,替代一部分光猫功能;
  • +
  • 7.智能DNS配置与去广告;
  • +
  • 8.VPN配置回家;
  • +
  • 9.实现透明代理。
  • +
+
+

剩余专业路由功能可以由ROS替代,服务则跑在NAS系统上,避免ALL in Boom!

+
+

大致思路

+
    +
  • 使用高性能的X86主机管理拨号和 DHCP 内网的工作,其他无线路由器桥接做AP,Mesh组网;
  • +
  • 使用绕过中国流量模式,国内流量不经过代理内核直接直连,加快国内网站访问。保持尽可能高的 NAT 等级;
  • +
  • 不使用旁路由,所有流量过主路由;由于第二点代理挂了也不影响国内正常上网;
  • +
  • 国内外域名分流查询,国内域名查运营商 DNS ,国外域名经代理查国外 DoH ,直接返回真实 IP;
  • +
  • 良好的国内 IPv6 支持,只对国内域名返回 IPv6 AAAA 结果,国外域名只用 IPv4;
  • +
  • 兼容 Adguard Home ,方便管理域名黑白名单;
  • +
  • 对能直连的国外服务能返回最优的节点,而不是绕路其他地方;
  • +
+

选择合适的设备

+

无论是传统的无线路由器还是小主机都有成为openwrt路由的潜力。截止到今天,已经有20多个品牌(小米,华硕,锐捷,华三等)30多种架构(x86,ipq,bcm,mtd等)支持刷入openwrt;你可以在这个网站找到符合你预算和其他要求的,能刷机的路由器。 +传统家用无线路由器由于主频低,内存小,并不适合作为软路由;而 NAS-软路由一体式 又有 all in boom 的风险,因此推荐X86平台作为物理机。当然,也可以采用 armbian 平台或是开发板,例如网心云老母鸡、树莓派等设备。截至本文撰写时间,二手平台上的价格不太利好:一台J1900平台的售价往往在200左右,而专门的多网口工控机价格在200到1000不等,树莓派更是成为了理财产品,需要慎重选择。

+

选择合适的系统

+

除了openwrt主线外,还可以选择:

+
    +
  • +

    LEDE 高质量,更新快速,具有新特性的openwrt分支。

    +
  • +
  • +

    iStoreOS iStoreOS是openwrt的一个分支,iStoreOS 提供了软件中心:iStore,以及较美观的界面和docker支持,对新手体验较好。

    +
  • +
  • +

    ImmortalWrt 是一个原版openwrt的分支,中文优化好,更新也勤快,内置镜像源可以直连下载&更新。

    +
  • +
+

如何得到一个openwrt系统

+
    +
  • 可以在恩山论坛上使用他人编译好的现成的镜像,如"高大全","精品小包"等等,但存在一定风险;
  • +
  • 可以使用官方固件下载得到一个最小化的系统,再一步步添加自己要用的包;注意需要根据你的uboot来选择,注意固件名称是否带了uboot_mod!
  • +
  • 可以使用Openwrt 在线编译Openwrt.ai在线编译 +一个固件;
  • +
  • 可以使用GitHub action 云编译一个固件;
  • +
  • 可以在本地linux环境中进行编译。
  • +
+

X86平台安装准备:

+ +

X86平台安装流程:

+

1.进入PE环境:

+
    +
  • 打开微PE,将其安装进U盘中,安装完成后将 img 工具和 openwrt 包一起放进去;
  • +
  • 将U盘插入目标主机,进入 BIOS-boot 设置U盘优先启动,各主板进入 BIOS 的按键不同,不确定的话建议都试一遍。
  • +
+

2.格式化硬盘并写盘

+
    +
  • 进入PE环境中,可以看到存在名为“分区助手”的软件,打开它并将目标主机硬盘格式化;注意不要分区!不要分区!不要设置文件系统!否则后续可能无法编译!点击左上角提交并执行
  • +
  • 打开img写盘工具,将openwrt包写入硬盘,注意不要写进U盘里。
  • +
+

3.进入配置界面

+
    +
  • 重启系统并快速拔出U盘,避免重新进入PE;这时系统开始运行了。注意Esir固件是不跑码的,无需担心。- 一个U盘与一台双网口物理机
  • +
  • 当看到 please press Enter to activate this console这个提示的时候系统就安装完毕了。可使用 passwd 命令设置密码。软路由将自动获取IP地址,随后我们在浏览器中打开该地址,即可看到 Lucl 界面。
  • +
+

4.如果你使用官方固件,注意:

+
    +
  • 硬盘空间有一部分没有被格式化,可以手动格式化为ext4并挂载。
  • +
  • 注意初始IP往往是192.168.1.1,如果和光猫冲突需要在网络-接口中更改。
  • +
  • 基本系统主题比较简陋,可以使用luci-theme-argon。
  • +
  • 刷错主题无法打开luci:通过 SSH 登录路由器,切换到另一个已知正常的主题(例如 Bootstrap): +uci set luci.main.mediaurlbase='/luci-static/bootstrap' uci commit luci /etc/init.d/uhttpd restart +然后重新访问 Web 界面,查看是否恢复正常。
  • +
  • 一般要安装的包:
  • +
+
openssh-sftp-server
+libpcap
+luci-app-upnp
+luci-app-ttyd
+kmod-nft-xxx
+
+

X86平台本地编译完整openwrt

+
    +
  • +

    系统版本:Debian 11 或者 Ubuntu LTS

    +
  • +
  • +

    网络要求:科学上网环境,配置推荐 2H4G 以上

    +
  • +
  • +

    编译依赖

    +
  • +
+
sudo apt update
+sudo apt install -y \
+  ack antlr3 asciidoc autoconf automake autopoint binutils bison build-essential \
+  bzip2 ccache clang cmake cpio curl device-tree-compiler diffutils diffstat findutils flex gawk \
+  gcc-multilib g++-multilib git gettext gperf grep haveged help2man intltool \
+  libelf-dev libfuse-dev libgmp3-dev libgl1-mesa-dev libgraphene-1.0-dev libglib2.0-dev \
+  libltdl-dev libmpc-dev libmpfr-dev libncurses-dev libpython3-dev libreadline-dev libssl-dev \
+  libtool lrzsz make mesa-common-dev msmtp ninja-build p7zip p7zip-full patch pkgconf \
+  perl python-is-python3 python3 python3-dev python3-distutils-extra python3-pip python3-pyelftools \
+  python3-setuptools qemu-utils rsync scons squashfs-tools subversion swig texinfo uglifyjs \
+  upx-ucl unzip vim wget gnu-which xmlto xxd zlib1g-dev genisoimage llvm llvm-runtime docutils-common \
+  ecj fastjar java-wrappers libeclipse-jdt-core-java libgnutls-dane0t64 \
+  libgnutls-openssl27t64 libgnutls28-dev libidn2-dev libp11-kit-dev libtasn1-6-dev libtasn1-doc \
+  libunbound8 libyaml-dev lld lld-18 nettle-dev python3-docutils python3-ply python3-roman re2c
+
+
    +
  • 清理
  • +
+
sudo apt autoremove --purge
+sudo apt clean
+
+
    +
  • 新建一个用户,用于编译固件(可选)
  • +
+
useradd -m openwrt  # 新建一个名为 openwrt 的用户
+
+
+

不可以使用Root用户进行编译!!!

+
+
    +
  • 修改用户默认的 Shell
  • +
+
apt install -y sudo
+usermod -s /bin/bash openwrt
+
+
    +
  • 切换用户
  • +
+
su openwrt
+cd ~
+
+
    +
  • 拉取源码,这里用的是 LEDE 分支源码:
  • +
+
git clone https://github.com/coolsnowwolf/lede
+cd lede
+
+

目录说明

+
    +
  • +

    buildroot: OpenWrt 的核心目录,包含构建系统相关的文件。

    +
      +
    • feeds.conf.default:定义软件包源的配置文件。
    • +
    • files/:存放自定义文件,用于覆盖默认的 root 文件系统。
    • +
    +
  • +
  • +

    target: 包含目标设备架构的配置和构建信息。

    +
      +
    • linux/:包含与 Linux 内核相关的代码和配置。
    • +
    • generic/:通用配置文件。
    • +
    • platform/:针对具体设备平台的特定配置。
    • +
    +
  • +
  • +

    package: 包含所有 OpenWrt 的软件包。

    +
      +
    • base/:基本功能相关的软件包(如 BusyBox、opkg)。
    • +
    • kernel/:与内核相关的补丁或模块。
    • +
    • network/:网络工具和协议(如 DHCP、DNS)。
    • +
    • utils/:各种实用工具(如编解码器、文件工具)。
    • +
    +
  • +
  • +

    config: 存放默认配置文件,例如 Config.in,用于定义菜单项。

    +
  • +
  • +

    scripts: 构建过程中使用的辅助脚本(如生成补丁、编译镜像)。

    +
  • +
  • +

    toolchain: 构建工具链所需的文件,如编译器、链接器。

    +
  • +
  • +

    tools: 一些构建系统依赖的额外工具(如 autoconfzlib)。

    +
  • +
  • +

    include: 存放 Makefile 的通用模板和其他全局定义文件。

    +
  • +
  • +

    feeds: 包含通过 feeds.conf 配置的外部软件包源。

    +
  • +
  • +

    documentation: 包含与 OpenWrt 项目相关的文档,如构建指南和开发文档。

    +
  • +
  • +

    添加软件源,可自行添加软件源至 feeds.conf.default 文件,也可以直接git添加需要的软件到lede目录下:

    +
  • +
+
vim feeds.conf.default
+
+
常用源
+src-git kenzo https://github.com/kenzok8/openwrt-packages
+src-git small https://github.com/kenzok8/small
+src-git haibo https://github.com/haiibo/openwrt-packages
+src-git liuran001 https://github.com/liuran001/openwrt-packages
+
+
    +
  • 单独添加(在更新并安装插件之前执行)例如:
  • +
+
git clone https://github.com/chenmozhijin/turboacc.git
+
+
    +
  • 更新并安装插件
  • +
+
./scripts/feeds clean
+./scripts/feeds update -a
+./scripts/feeds install -a
+
+
    +
  • 自定义配置
  • +
+

修改默认IP为 10.0.0.2

+
sed -i 's/192.168.1.1/192.168.2.1/g' package/base-files/files/bin/config_generate
+
+

修改默认主机名

+
sed -i '/uci commit system/i\uci set system.@system[0].hostname='OpenWrt'' package/lean/default-settings/files/zzz-default-settings
+
+

加入编译者信息

+
sed -i "s/OpenWrt /smith build $(TZ=UTC-8 date "+%Y.%m.%d") @ OpenWrt /g" package/lean/default-settings/files/zzz-default-settings
+
+

修改默认主题

+
sed -i "s/luci-theme-bootstrap/luci-theme-argon/g" feeds/luci/collections/luci/Makefile
+
+

执行 make menuconfig 命令进入编译菜单。

+

编译配置菜单说明(部分)

+
Target System (Broadcom BCM27xx)     # 选择处理器架构
+└── Subtarget (BCM2711 boards (64 bit))     # 选择处理器
+    └── Target Profile (Raspberry Pi 4B/400/4CM (64bit))     # 预制配置文件
+        └── Target Images     # 固件映像设置
+            └── ramdisk     # 内存盘
+                ├── Compression     # 压缩等级 (none 表示不压缩)
+                ├── Root filesystem archives     # 根文件系统存档类型
+                │   ├── cpio.gz
+                │   └── tar.gz
+                ├── Root filesystem images     # 根文件系统格式
+                │   ├── ext4     # 适用于大容量闪存
+                │   ├── squashfs     # 适用于小容量闪存
+                │   └── Gzip images     # Gzip 存档
+                └── Image Options
+                    ├── Kernel partition size     # 内核分区大小
+                    ├── Root filesystem partition size     # 跟文件系统分区大小
+                    └── Make /var persistent     # 持久化 /var
+
+Enable experimental features by default     # 默认启用实验性功能
+Global build settings     # 全局编译设置
+Advanced configuration options (for developers)     # 高级选项(仅供开发者)
+Build the OpenWrt Image Builder     # 编译 OpenWrt 镜像编译器
+Build the OpenWrt SDK     # 编译 OpenWrt SDK
+Package the OpenWrt-based Toolchain     # 打包 OpenWrt 工具链
+Image configuration     # 镜像选项
+
+Base system     # 基本组件
+Administration     # 管理员工具
+Boot Loaders     # 引导程序
+Development     # 开发者工具
+Extra packages     # 额外包
+Firmware     # 固件工具
+Fonts     # 字体
+Kernel modules     # 内核模块
+Languages     # 额外的语言 (Python3, PHP, NodeJS 等)
+Libraries     # 系统库
+LuCI     # LuCI 插件(一般只需修改应用和主题)
+└── Collections
+└── Modules
+└── Applications
+└── Themes
+└── Protocols
+└── Libraries
+└── default-settings     # 默认选项(自动配置语言包)
+
+Mail     # 邮件
+Multimedia     # 多媒体
+Network     # 网络相关
+Sound     # 音频
+Utilities     # 各类实用软件(比如 VIM)
+Xorg
+
+

菜单选项说明

+

选择 CPU 类型

+
Target System (x86) --> # 软路由选择 x86,硬路由根据型号厂家自行选择
+
+Subtarget (x86_64) --> # CPU 子选项
+
+Target Profile (Generic x86/64) --> # 厂家具体型号
+
+

设置镜像编译的格式(squashfs,ext4)

+
Target Images --> # 默认 squashfs
+
+

添加较多插件时,为了避免空间不足,建议修改下面两项默认大小(x86/64)

+
Target Images --> (16) Kernel partition size (in MB) # 默认是16,建议修改为256
+
+

开启 IPv6 支持

+
Extra packages --> ipv6helper(选定这个后,下面几项会自动选择)
+
+

开启适用于 VMware 的 VMware Tools

+
Utilities --> open-vm-tools
+
+Utilities --> open-vm-tools-fuse
+
+

选择插件

+
LuCI --> Applications # 根据需要选择,* 代表编入固件,M 表示编译成模块或者IPK包,为空表示不编译
+
+

选择主题

+
LuCI --> Themes # 选择喜欢的主题,可以选多个
+
+

配置完成后使用编译菜单底部的 Save 保存,然后退出菜单 Exit,开始下载软件包

+
    +
  • 预下载编译所需的软件包
  • +
+
make download -j8
+
+
    +
  • 检查文件完整性
  • +
+
find dl -size -1024c -exec ls -l {} \;
+
+

检查文件完整性命令可以列出下载不完整的文件,小于1k的文件属于下载不完整,如果存在则用下面的命令删除,然后重新下载编译所需的软件包,再次检查.确认所有文件完整可大大提高编译成功率,避免浪费时间

+
find dl -size -1024c -exec rm -f {} \;
+
+

最后编译固件,编译完成后输出路径是 bin/targets,默认密码是 password.

+
    +
  • 编译固件(-j 后面是线程数,首次编译推荐用单线程)
  • +
+
make V=s -j1
+
+
    +
  • 二次编译
  • +
+

拉取最新 OpenWrt 源码和更新 feeds 源中的软件包源码

+
cd lede
+
+git pull
+
+./scripts/feeds update -a
+
+./scripts/feeds install -a
+
+

清除旧的编译产物和目录(可选)

+
make clean
+
+
    +
  • 源码有大规模更新或者内核更新后执行,以保证编译质量;此操作会删除 /bin 和 /build_dir 目录中的文件
  • +
+
make dirclean
+
+
+

更换架构编译前必须执行

+
+
+

此操作会删除 /bin 和 /build_dir 目录的中的文件(make clean),以及 /staging_dir、/toolchain、/tmp 和 /logs 中的文件

+
+

同首次编译,多线程编译失败后自动进入单线程编译,失败则输出详细日志

+
make defconfig
+
+make download -j8
+
+find dl -size -1024c -exec ls -l {} \;
+
+make -j$(nproc) || make -j1 || make -j1 V=s
+
+

如果需要重新配置

+
rm -rf ./tmp && rm -rf .config # 清除临时文件和编译配置文件
+
+make menuconfig
+
+make download -j8
+
+find dl -size -1024c -exec ls -l {} \;
+
+make -j$(nproc) || make -j1 || make -j1 V=s
+
+

Arm平台安装OpenWrt:

+

相比X86平台,arm架构的设备兼容性不高,不能随便找一个包就能安装。以下是一般步骤:

+
    +
  • +

    首先得知道你的设备的CPU,比如ipq40XX系列,然后在对应的仓库查看并下载包体。

    +
  • +
  • +

    当然也可以在这里直接下载相关型号对应的固件,其中 Sysupgrade 映像是用来更新现有运行 OpenWrt 的设备,使用 Factory 映像在首次刷机时刷入。

    +
  • +
  • +

    随后开启Telnet或者SSH或者TTL串口连接到路由器,将对应的Uboot刷入,如果没有适配的包就无法刷openwrt。

    +
  • +
  • +

    通过Uboot的网络界面刷入Factory包,随后就可以在后台(如192.168.1.1)进入openwrt的管理界面。

    +
  • +
+

在ubuntu上单独编译openwrt的ipk包

+

这里以ubuntu环境为例,我们假设你有一台虚拟机或者WSL。

+
+

注意编译不能使用Root用户!

+
+

随后安装编译依赖的各个包:

+
sudo apt update
+sudo apt install -y \
+  ack antlr3 asciidoc autoconf automake autopoint binutils bison build-essential \
+  bzip2 ccache clang cmake cpio curl device-tree-compiler diffutils diffstat findutils flex gawk \
+  gcc-multilib g++-multilib git gettext gperf grep haveged help2man intltool \
+  libelf-dev libfuse-dev libgmp3-dev libgl1-mesa-dev libgraphene-1.0-dev libglib2.0-dev \
+  libltdl-dev libmpc-dev libmpfr-dev libncurses-dev libpython3-dev libreadline-dev libssl-dev \
+  libtool lrzsz make mesa-common-dev msmtp ninja-build p7zip p7zip-full patch pkgconf \
+  perl python-is-python3 python3 python3-dev python3-distutils-extra python3-pip python3-pyelftools \
+  python3-setuptools qemu-utils rsync scons squashfs-tools subversion swig texinfo uglifyjs \
+  upx-ucl unzip vim wget gnu-which xmlto xxd zlib1g-dev genisoimage llvm llvm-runtime docutils-common \
+  ecj fastjar java-wrappers libeclipse-jdt-core-java libgnutls-dane0t64 \
+  libgnutls-openssl27t64 libgnutls28-dev libidn2-dev libp11-kit-dev libtasn1-6-dev libtasn1-doc \
+  libunbound8 libyaml-dev lld lld-18 nettle-dev python3-docutils python3-ply python3-roman re2c
+
+

随后下载我们刷入openwrt的对应的SDK包,如

+
git clone https://github.com/immortalwrt/immortalwrt.git
+
+

下载和安装仓库信息

+
./scripts/feeds update -a
+./scripts/feeds install -a
+
+

下载并选中我们需要编译的包,这里以inyn为例:

+
git clone https://github.com/diredocks/openwrt-inyn.git ./package/inyn
+make menuconfig
+
+

menuconfig 的命令行界面中,选中 Network -> inyn 将其首部调整为 <M> 表示按需编译,最后选中 Save -> OK -> Exit 保存配置信息,然后 Exit 退出配置。

+

编译 inyn 软件包

+
make package/inyn/compile V=s
+## 如果不行则需要先编译工具链,即为 make j=4 ,j为CPU核数
+
+

Github Actions 编译OpenWrt

+

Github为我们提供了免费的E5主机用来编译。

+
    +
  • +

    首先Fork这个仓库,可以看到有许多现成的配置,在顶栏actions里面可以直接启动一个Workflow来编译。

    +
  • +
  • +

    大体架构是选择源码 -- 机型 -- 版本 -- 插件/主题 -- 配置(IP/密码/Hostname/编译者),由一个config文件管理,这个文件在前面也提到过,可以在本地生成并上传;

    +
  • +
  • +

    想要什么插件可以直接git clone过来原仓库,如果你想要添加其他架构和设备,这里使用templet里面的init.toml来创建,按照类似的格式填好;

    +
  • +
  • +

    在actions里面运行produce,注意这需要GitHub Personal Access Token (PAT);如果没有,必须先添加:

    +
  • +
  • +

    打开 GitHub,进入GitHub Developer Settings点击 “Generate new token (classic)”,勾选所需权限(最关键的是 repo 和 workflow):✅ repo(所有子权限)✅ workflow✅ read:packages Token 过期时间:选择 “No expiration”(不过期),否则过期后需要重新生成。点击 “Generate token” +复制 Token(只显示一次,一定要保存好!)

    +
  • +
  • +

    然后添加 PRODUCE_DEVICEGitHub Secrets, +首先进入你的 GitHub 仓库,依次进入:Settings(设置)- Secrets and variables-Actions-New repository secret 名称为PRODUCE_DEVICE,值为粘贴刚刚复制的 GitHub Token,点击 “Add secret” 完成添加。

    +
  • +
  • +

    随后在actions里面运行produce,完成后即可出现新架构的编译按钮.

    +
  • +
+

常用命令:

+
# 更新软件列表
+opkg update
+
+# 更新所有 LUCI 插件
+opkg list-upgradable | grep luci- | cut -f 1 -d ' ' | xargs opkg upgrade
+
+# 如果要更新所有软件,包括 OpenWRT 内核、固件等
+opkg list-upgradable | cut -f 1 -d ' ' | xargs opkg upgrade
+
+
+

新版本的openwrt(24.10)已经改用APK包管理器。

+
+

常用科学插件

+ + + + +
特性HomeProxyOpenClashPasswallShellClash
核心Sing-box、XrayClashXray、Sing-boxClash、Xray、Sing-box
UI 管理✅(Web UI、桌面端 GUI)✅(OpenClash Web UI)✅(Luci Web UI)❌(Shell 终端管理)
适用场景性能较好,但分流设置复杂适用于clash系,机场首选操作简单,分流完善,但对路由器性能要求较高没有UI界面,性能最好,支持完善,可以通过clashapi安装UI
+

校园网多设备防检测

+

常见检测方法

+
    +
  • TTL检测法 解法:插件统一修复或使用桥接;使用kmod-iptables-ipot模块;
  • +
  • User-Agent 解法:统一经过singbox代理或使用UA2F/UA3F;
  • +
  • 时间戳检测法 解法:统一NTP服务器;
  • +
+

高性能开销检测方法

+
    +
  • IP-ID检测法 解法:UDP over TCP或rkp-IPid;
  • +
  • Flash cookie 解法:内置防火墙组件;
  • +
  • DPI检测法 深度包检测特征值 解法:代理协议;
  • +
+
+

高性能开销的检测方法会浪费大量性能,一般很少有学校这么做。IP-ID和Flash检测法如今已经不多见。

+
+

TTL修复:

+
依赖包
+opkg install kmod-nft-core kmod-nft-bridge kmod-nft-net kmod-nft-offload kmod-nft-nat
+
+首先检查 mangle 表是否存在
+nft list tables
+
+创建 mangle 表(如果不存在)
+nft add table ip mangle
+
+创建 POSTROUTING 链(如果不存在)
+nft add chain ip mangle POSTROUTING { type nat hook postrouting priority 0 \; }
+
+
+添加 TTL 规则
+nft add rule ip mangle POSTROUTING ip ttl set 64
+
+检查规则是否生效
+nft list table ip mangle
+
+

Openwrt改AP模式

+

有时候我们使用X86做主路由,想让无线路由器只起到发射信号的作用,就可以将其改为AP模式,一般步骤为:

+
    +
  • 更改lan地址,将lan口地址改到主路由下的一个IP;
  • +
  • 关闭DHCP服务;
  • +
  • 关闭WAN口;
  • +
  • 关闭防火墙的禁止转发规则,全部允许;
  • +
  • 将X86主路由的网线插到AP的任意一个LAN口。
  • +
+ + + +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/awesome-pve-mcsm/index.html b/public/awesome-pve-mcsm/index.html new file mode 100644 index 0000000..7f4a6cf --- /dev/null +++ b/public/awesome-pve-mcsm/index.html @@ -0,0 +1,296 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

综合工程:PVE安装与MC服务器搭建

+ + + + + + +
+

前言 假期将至,不少家里有闲置设备的小伙伴想尝试开设一个我的世界(Minecraft)服务器,却不知从何下手。本文以 PVE-Debian-MCSM 为主线介绍其部署流程。

+

什么是PVE?

+

PVE (全称 Proxmox Virtual Environment) 是一款开源免费的虚拟化环境平台,同时支持KVM 虚拟机和 LXC 容器。它基于 Debian 和 KVM 技术开发,可在一台 PC 或服务器上同时运行Linux、OpenWRT、Windows 等,实现计算、网络、存储一体化解决方案,即所谓的“all in one”。类似的平台还有ESXi、Unraid等。

+

什么是MCSM?

+

MCSManager 面板(简称:MCSM 面板)是一款全中文,轻量级,开箱即用,多实例和支持 Docker 的 Minecraft 服务端管理面板。

+

此软件在 Minecraft 和其他游戏社区内中已有一定的流行程度,它可以帮助你集中管理多个物理服务器,动态在任何主机上创建游戏服务端,并且提供安全可靠的多用户权限系统,可以很轻松的帮助你管理多个服务器。 +具体步骤:安装PVE并优化,开设虚拟机并安装Debian,安装mscm界面并开设实例,配置网络服务。

+

准备工作

+ +

一.安装PVE并优化

+

1.将下载好的镜像用Rufus写入U盘。

+

2.将U盘插到目标主机上面,进入BIOS-boot设置启动顺序。这里我使用二手浪潮服务器X99主板,矿龙电源以及一块128G的SSD固态。注意:大部分服务器主板有机箱入侵检测机制,需要在说明书中找到特定针脚并用导电帽盖上,否则无法开机。

+

3.进入安装界面,选择install; +随后跑码,进入如下界面,同意协议: +设置硬盘与文件类型,可以选择ext4或者btrfs; +选择国家与地区,这里需要手打出China; +随后设置密码与邮件,邮件可以随便填: +然后设置网络连接,这里插网线就有地址;设置主机名,并记下内网IP地址; +检查无误后开始安装: +安装完成后 reboot。

+

4.浏览器打开 PVE 地址,进入系统后我们需要给PVE换源。

+

换源

+

禁用 Ceph 企业仓库:

+
nano /etc/apt/sources.list.d/ceph.list
+
+

将文件内容注释掉或删除。

+

编辑仓库源文件:

+
nano /etc/apt/sources.list.d/pve-enterprise.list
+
+

将文件内容注释掉或删除;

+

启用社区仓库:

+

确保社区仓库已启用。编辑社区仓库文件:

+
nano /etc/apt/sources.list.d/pve-no-subscription.list
+
+

确保文件内容如下:

+
deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription
+
+

二.新建虚拟机并安装Debian

+

1.找到 local-btrfs(pve),在其中的 ISO 中上传下载好的 Debian 镜像;

+

2.随后创建虚拟机,选择 Debian 镜像并设置 CPU 核数与硬盘、内存大小;

+

3.一路确认后开机进入命令行界面,即可开始Debian安装。我们选择graphical install:

+

4.选择国家和语言,随后自动配置网络;

+

5.设置主机名,跳过域名设置;设置 root 账户名和密码、普通用户账户名与密码;

+

6.对磁盘进行分区,由于是虚拟机我们选择使用整个磁盘;

+

7.安装基本系统,随后将进入包管理器和大组件安装;

+

我们选择清华源,速度较快。注意:Debian 安装时默认开启安全源,这个源是国外的所以下载速度极慢,因此还需要修改配置文件。

+

在安装步骤进入到选择安装的桌面环境和软件时, 键入 Ctrl+Alt+F2 可以看到从图形界面转到了tty命令终端, 键入 Enter +这里修改软件源配置文件

+
nano /target/etc/apt/sources.list
+
+

修改debian-security源地址  http://mirrors.ustc.edu.cn  目测最快

+
deb http://mirrors.ustc.edu.cn/debian-security bullseye-security main
+
+

修改后 Ctrl+X 退出保存,然后退出终端重新进入界面继续安装,键入 Ctrl+Alt+F5。

+

下载需要一些时间,此时可以饮口茶先,随后看到如下界面:

+

由于是服务器所以不需要桌面环境:

+

安装 grub 引导:

+

随后安装完成,reboot后进入mscm的安装。

+

三.安装MCSM并开设实例

+

1.开机进入tty1界面

+

2.安装JAVA环境,不同版本的游戏的 Java 版本也不同。这里我们使用1.19版,需要安装 Java18。

+

安装 wget 和 下载 Java18

+

apt install wget && wget http://img.zeruns.tech/down/Java/OpenJDK18U-jre_x64_linux_hotspot_18.0.1_10.tar.gz

+

创建安装目录

+

mkdir /usr/local/java/

+

解压当前目录下的 JDK 压缩文件

+

tar -zxvf OpenJDK18U-jre_x64_linux_hotspot_18.0.1_10.tar.gz -C /usr/local/java/

+

软链接程序到环境变量中

+

ln -sf /usr/local/java/jdk-18.0.1+10-jre/bin/java /usr/bin/java

+

测试是否安装正常,显示 openjdk version "18.0.1" 2022-04-19 则为正常

+

java -version

+

3.端口开发,面板需要 23333和24444 端口,游戏服务器默认端口是 25565。

+

在 PVE-防火墙中打开它们。如果还是不行,执行如下命令:

+
systemctl stop firewalld
+
+systemctl disable firewalld
+
+service iptables stop
+
+

从而关闭防火墙。

+

4.安装面板,这里使用一键安装命令(注意该脚本仅适用于 AMD64 架构)

+

wget -qO- https://gitee.com/mcsmanager/script/raw/master/setup.sh | bash

+

执行完成后,使用 systemctl start mcsm-{web,daemon} 即可启动面板服务。使用 systemctl enable mcsm-{daemon,web}.service 实现开机自启。

+

5.在浏览器中打开该地址加上23333端口后缀,即可看到面板,账户为root,密码为123456。

+

6.新建实例,上传 Purpur1.19 服务端,设置名称随后开启实例

+

7.随后我们可以在 配置文件中设置游戏的相关选项,如关闭正版验证等。

+

8.大功告成,此时打开 HMCL 启动器,即可加入游戏。

+

四.配置联机网络

+

1.此时不要忘记需要和小伙伴们一起玩耍。如果你家里有公网固定 IPv4 或者 IPv6,直接输入联机即可;如果没有公网IP,此时就需要进行内网穿透或者DDNS。

+

这里介绍一种名为 zerotier 的工具。

+

2.首先在 https://www.zerotier.com/ 注册并创建一个私有网络;

+

3.首先在虚拟机中安装 curl 命令支持

+

apt-get install curl

+

4.安装gnupg非对称信息加密系统,通讯所需必备软件

+

apt-get install gnupg

+

5.安装 ZeroTier

+

curl -s https://install.zerotier.com/ | bash

+

安装成功后提示如下:

+

Success! You are ZeroTier address [ xxxxxxxxx ].

+

方括号内地址为类似于MAC地址。

+

6.设定开机自启动(分别执行如下命令)

+

systemctl start zerotier-one.service

+

systemctl enable zerotier-one.service

+

7.加入自己的私有网络

+

zerotier-cli join xxxxxxxxx

+

8.大功告成!此时只要让小伙伴们下载 zerotier 客户端并加入相同的私有网络,即可一起快乐联机!

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/awesome-vm-android/index.html b/public/awesome-vm-android/index.html new file mode 100644 index 0000000..4d11ec4 --- /dev/null +++ b/public/awesome-vm-android/index.html @@ -0,0 +1,457 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

综合工程:linux搭建安卓虚拟机

+ + + + + + +
+

前言 linux搭建安卓虚拟机有Waydroid,QEMU和Docker三种方案,各有不同。

+

Waydroid

+

Waydroid是Anbox配合Halium技术开发的LXC Android容器,可在GNU/Linux系统执行Android APP。以下是Waydroid的特色功能:

+
    +
  • 开源
  • +
  • 支持x86与ARM架构
  • +
  • 与宿主机共用剪切板
  • +
  • 直接使用电脑显卡硬件加速
  • +
  • 內建GAPPS,可以使用Google Play
  • +
  • 支持Magisk
  • +
+
+

Waydroid执行时的Android系统资料放在~/.local/share/waydroid/data/,系统映像档位于/var/lib/waydroid,APP图示位于~/.local/share/applications/

+
+

安装前准备

+

目前Waydroid只支持Intel和AMD的显卡,对于 NVIDIA 显卡(除 Tegra 系列外),Waydroid 不支持硬件加速,推荐使用软件渲染或QEMU方案。

+
    +
  • Waydroid必须使用Wayland,用此命令检查当前系统是否为Wayland:
  • +
+
echo $XDG_SESSION_TYPE
+
+

若显示X11代表不是Wayland。GNOME和KDE可在登入画面切换至Wayland工作阶段。

+
    +
  • Waydroid要求Linux核心支持binder核心模组,但Arch Linux预设的linux核心並无开启此选项,因此需要从AUR安装binder_linux-dkms补齐。
  • +
+
paru -S  binder_linux-dkms
+
+
    +
  • 安装后载入binder核心模组
  • +
+
sudo modprobe binder-linux devices=binder,hwbinder,vndbinder
+
+
    +
  • 设定开机自动载入核心模组
  • +
+
echo "binder_linux" | sudo tee -a /etc/modules-load.d/binder_linux.conf
+
+echo "options binder_linux devices=binder,hwbinder,vndbinder" | sudo tee -a /etc/modprobe.d/binder_linux.conf
+
+

安装Waydroid

+
    +
  • 安装以下软件包,让Linux与Waydroid共享剪切板
  • +
+
paru -S wl-clipboard xclip
+paru -S python-pyclip
+
+
    +
  • 安装Waydroid
  • +
+
paru -S waydroid
+
+
    +
  • 初始化Waydroid,下载含有GAPPS的Android系统映像档
  • +
+
sudo waydroid init -s GAPPS -f
+
+
    +
  • 启动Waydroid容器服务
  • +
+
sudo systemctl start waydroid-container
+
+

常用命令

+
    +
  • 开机自动启动
  • +
+
sudo systemctl enable waydroid-container
+
+
    +
  • 点选应用列表的「Waydroid」图示开启主画面,或者使用命令:
  • +
+
waydroid show-full-ui
+
+
    +
  • 若Waydroid无法连上网路,开放UFW防火墙:
  • +
+
sudo ufw allow 53
+sudo ufw allow 67
+sudo ufw default allow FORWARD
+sudo ufw reload
+sudo systemctl restart waydroid-container
+
+
    +
  • 重启Waydroid
  • +
+
sudo systemctl restart waydroid-container
+
+
    +
  • 启动/停止Waydroid容器服务
  • +
+
sudo systemctl start waydroid-container
+sudo systemctl stop waydroid-container
+
+
    +
  • 用命令开启Waydroid主画面
  • +
+
waydroid show-full-ui
+
+
    +
  • 查看系统错误讯息
  • +
+
waydroid log
+sudo waydroid logcat
+
+
    +
  • 强制屏幕旋转
  • +
+

安装Rotation Control这类APP,即可强制调整Waydroid屏幕方向.

+
    +
  • 模拟Wifi
  • +
+

安装Package Manager,用於查看APP的软件包名称。

+

部份APP会要求开启Wifi才能上网,那么就如它所愿,开启fake wifi:

+
waydroid prop set persist.waydroid.fake_wifi "软件包名称"
+
+

例如给Fate/Go游戏开启模拟Wifi:

+
waydroid prop set persist.waydroid.fake_wifi "com.aniplex.fategrandorder"
+
+
    +
  • 模拟触控功能
  • +
+

安装Package Manager,用於查看APP的软件包名称。有些APP认不到鼠标点击,需要启用模拟触控(fake touch):

+
waydroid prop set persist.waydroid.fake_touch "软件包名称"
+
+

例如给Fate/Go游戏开启模拟触控:

+
waydroid prop set persist.waydroid.fake_touch "com.aniplex.fategrandorder"
+
+
    +
  • 用命令安装APK
  • +
+
waydroid app install <APK档案路径>.apk
+
+
    +
  • 进入ADB Shell
  • +
+
sudo waydroid shell
+
+
    +
  • 开启多视窗模式
  • +
+

Waydroid的多视窗模式,看起来像Linux的原生应用。启动后按F11改回来。

+
waydroid prop set persist.waydroid.multi_windows true
+sudo systemctl restart waydroid-container
+
+

将Waydroid注册为Google装置

+

Waydroid第一次开机可能会收到Device is not Play Protect certified的通知,无法登入Google账号。

+

用以下命令取得Waydroid的装置ID。该命令会印出一长串数字。

+
sudo waydroid shell
+
+ANDROID_RUNTIME_ROOT=/apex/com.android.runtime ANDROID_DATA=/data ANDROID_TZDATA_ROOT=/apex/com.android.tzdata ANDROID_I18N_ROOT=/apex/com.android.i18n sqlite3 /data/data/com.google.android.gsf/databases/gservices.db "select * from main where name = \"android_id\";"
+
+

开启装置注册页面,登入Google账号,输入装置ID注册,等个半小时应该就能登入Google账号了。如果还是不行就重新启动Waydroid容器服务:

+
sudo systemctl restart waydroid-container
+
+

现在可以安装APP了,Google Play和F-Droid会自动筛出適合x86架构的APP。

+

QEMU/KVM

+

概述

+

Bliss OS 是基于 Android-x86 的开源系统,已更新至 Android 13,并内建 Google Play 商店,可直接运行 64 位 APK,无需额外转译器;在 Linux 上通过 QEMU/KVM + virglrenderer 实现 GPU 加速,使得在虚拟机中也能流畅体验手游。

+

为什么选择 Bliss OS?

+
    +
  • 版本更新快:Bliss OS 最新测试版基于 Android 13,而 Android-x86 官方仅更新至 Android 9。
  • +
  • 更完善的 ARM 转译:采用 Google libndk,可兼容 64 位 ARM-v8a APK;相比仅支持 32 位 ARM-v7 的 liboudini,兼容性大幅提升。
  • +
  • 丰富实用功能:预装强制旋转、按键映射、游戏模式、模拟触控点击、KernelSU(难以检测的 root 权限)和 Gearlock 恢复环境等增强工具,提升桌面化体验。
  • +
+

环境准备

+
    +
  • 硬件要求:CPU 要开启 VT-x/AMD-V,并加载 KVM 内核模块;Intel 10 代及更新集成 GPU 可用,AMD 同理;闭源 Nvidia 驱动下 virglrenderer 不稳定,不建议使用硬件加速。
  • +
  • 软件安装:在宿主机上安装 QEMU (≥8.1.1)、Libvirt、Virt-Manager,并部署 virglrenderer (≥0.10.4) 以获得半虚拟化 3D 加速;Ubuntu 与 Arch 安装方法分别见官方文档。
  • +
  • 性能调优:可参考 Red Hat 虚拟化性能调优指南,启用 IOMMU、调整 CPU 调度与内存缓存策略,以提升 KVM 性能。
  • +
+

安装流程与分区

+
    +
  1. 从官方站点下载带 GApps 的 Bliss OS 15.x ISO 镜像,并在 Virt-Manager 中新建虚拟机,选择 Q35 芯片组、UEFI (OVMF)
  2. +
  3. 推荐分配 ≥8 GB RAM、4 核 CPU 及 ≥64 GB 虚拟硬盘,并勾选 OpenGL、VirtIO 显示卡 + 3D 加速。
  4. +
  5. 进入 Bliss OS 安装器,使用 GPT 分区表: +
      +
    • 首分区 512 MB,类型 EFI (ef00),挂载点 /mnt/efi
    • +
    • 次分区 全盘剩余空间格式化为 Ext4,用于系统安装。
    • +
    +
  6. +
  7. 安装 GRUB、格式化分区后强制关机,移除 ISO 并重启,即可启动已启用 virglrenderer 加速的系统。
  8. +
+

分辨率调整

+
    +
  • 启动时选择 “Debug QEMU/KVM VirGL” 进入 shell,通过 blkid 找到 EFI 分区(如 /dev/sda1),挂载后编辑 /mnt/efi/boot/android.cfg: +
      +
    • linux $kd/kernel 行末添加 video=1920x1080
    • +
    • 修改 set gfxmode= 为相应分辨率,保存并重启即可生效。
    • +
    +
  • +
  • 如需更灵活调整,可在系统内安装 SecondScreen 等第三方工具强制改分辨率。
  • +
+

系统使用技巧

+
    +
  • 默认启用 Boringdroid 桌面模式,底部常驻任务栏;可在设置里为特定应用强制全屏运行。
  • +
  • 强制旋转:内置 Set Orientation 或使用更佳的 OHMAE Ryosuke 工具;屏幕录制推荐宿主机通过 OBS 采集 VM 窗口。
  • +
  • 多窗口:开发者选项启用“自由形式窗口”;Root 需在 KernelSU 中对指定应用授权,Termux 可提供终端环境。
  • +
  • ADB 调试:可通过无线 ADB 连接,并在 shell 中为 com.android.shell 授予 Root 权限。
  • +
+

手游实测

+
    +
  • 优先安装原生 x86 版游戏,减少 ARM 转译开销;多游戏如《水果忍者》、《Temple Run 2》均能流畅运行。
  • +
  • 部分大型游戏(如《原神》)因 virglrenderer 不稳定在着色器编译时易崩溃;《幻塔》可正常进入并游玩。
  • +
  • 若触控事件不响应,可启用 “Force Mouse Click as touch” 强制映射鼠标点击,但会导致滚轮失效;开启“游戏模式”可屏蔽通知并悬浮截屏。
  • +
+

Docker

+

概述

+

ReDroid(Remote-Android)是一款开源的容器化 Android 解决方案,支持在 x86 主机通过 Docker、Podman 或 Kubernetes 启动多实例 Android 系统,并提供 GPU 加速与多架构(arm64/amd64)支持,适用于云端游戏、自动化测试、虚拟手机等场景。本文从环境准备、部署配置、日常使用及进阶定制等方面,逐步讲解如何在 Linux 主机上用 Docker 容器运行并优化 ReDroid,使其能够流畅运行 ARM 架构的手游。

+

什么是 ReDroid?

+
    +
  • 项目简介:ReDroid 即 Remote-Android,是一个多架构、GPU 加速的“Android In Cloud”(AIC)方案,可在任何具备必要内核特性(如 binderfs)的 Linux 主机上部署 Android 容器。
  • +
  • 版本支持:活跃维护 Android 11–15 多个版本的镜像,并提供丰富的文档与社区支持。
  • +
  • 应用场景:适用于云游戏、自动化测试、连续集成中的 UI 测试、远程开发等多种场景。
  • +
+

环境与依赖

+
    +
  • 内核模块:宿主机需开启 binderfsashmem 等内核模块,部分发行版可能需安装 redroid-modules
  • +
  • GPU 加速:推荐使用 Intel/AMD 集成 GPU,避免闭源 NVIDIA 驱动下的不稳定性;也可在云端 GPU 实例上部署。
  • +
  • 软件需求:安装 Docker / Docker Compose(或 Podman)、ADB(Android Debug Bridge)和 Scrcpy,用于容器管理与远程调试、画面传输。
  • +
  • 硬件配置:8 GB 及以上内存、四核及以上 CPU、至少 20 GB 存储;若运行高负载游戏,推荐更高配置并开启 GPU 硬件加速。
  • +
+

部署与配置

+
    +
  1. 创建目录与编写 Compose 文件
    mkdir ~/redroid && cd ~/redroid
    +vim docker-compose.yml
    +
    +
  2. +
  3. 示例 docker-compose.yml
    version: '3.8'
    +services:
    +  redroid:
    +    image: redroid/redroid:11.0.0_gapps
    +    stdin_open: true
    +    tty: true
    +    privileged: true
    +    ports:
    +      - "127.0.0.1:5555:5555"
    +    volumes:
    +      - ./redroid-11-data:/data
    +    command:
    +      - androidboot.redroid_width=720
    +      - androidboot.redroid_height=1280
    +      - androidboot.redroid_dpi=320
    +      - androidboot.redroid_fps=60
    +      - androidboot.redroid_gpu_mode=host
    +      - ro.product.cpu.abilist0=x86_64,arm64-v8a,x86,armeabi-v7a,armeabi
    +      - ro.enable.native.bridge.exec=1
    +      - ro.dalvik.vm.native.bridge=libndk_translation.so
    +
    +
  4. +
  5. 启动容器
    sudo docker compose up -d
    +
    +
  6. +
+

日常使用

+
    +
  • ADB 连接与屏幕镜像
    adb connect localhost:5555
    +scrcpy -s localhost:5555 --audio-codec=aac
    +
    +
  • +
  • 安装 APK: +
      +
    • 使用 adb install your_app.apk
    • +
    • 或在 Scrcpy 界面中拖拽 APK 文件进行安装
    • +
    +
  • +
  • 停止与重启
    sudo docker compose down
    +sudo docker compose up -d
    +
    +
  • +
  • 数据持久化:所有数据保存在 ~/redroid/redroid-11-data,可备份或运行多实例。
  • +
+

高级操作与安全建议

+
    +
  • Google Play 验证:首次登录 Play Store 需获取设备 ID 并在 Google 控制台注册后重启容器。
  • +
  • 3D 加速检测:通过 AIDA64 等应用验证 GPU 加速是否生效。
  • +
  • 网络安全:只绑定本地回环地址监听 ADB 端口;如需外网访问,务必配置防火墙规则,避免安全风险。
  • +
+

定制镜像与 GApps

+
    +
  • 安装 GApps:下载 OpenGApps x86_64 Android 11 Pico 包,将其中 APK 拷贝到自建镜像的 system 目录,再在容器内推送并授权。
  • +
  • 自定义 libndk:从 Android Studio 模拟器提取 Google 官方 ARM 翻译库(libndk),在 Dockerfile 中加入到基于 redroid:13.0.0-latest 的自定义镜像,提升兼容性与性能。
  • +
+
+

🔗

+

如何在Linux安裝Bliss OS

+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/buttons.css b/public/buttons.css new file mode 100644 index 0000000..462f45e --- /dev/null +++ b/public/buttons.css @@ -0,0 +1 @@ +.button-container{display:table;margin-left:auto;margin-right:auto}button,.button,a.button{position:relative;display:flex;align-items:center;justify-content:center;padding:8px 18px;margin-bottom:5px;text-align:center;border-radius:8px;border:1px solid rgba(0,0,0,0);appearance:none;cursor:pointer;outline:none;}button.outline,.button.outline,a.button.outline{background:rgba(0,0,0,0);box-shadow:none;padding:8px 18px}button.outline :hover,.button.outline :hover,a.button.outline :hover{transform:none;box-shadow:none}button.primary,.button.primary,a.button.primary{box-shadow:0 4px 6px rgba(50,50,93,.11),0 1px 3px rgba(0,0,0,.08)}button.primary:hover,.button.primary:hover,a.button.primary:hover{box-shadow:0 2px 6px rgba(50,50,93,.21),0 1px 3px rgba(0,0,0,.08)}button.link,.button.link,a.button.link{background:none;font-size:1rem}button.small,.button.small,a.button.small{font-size:.8rem}button.wide,.button.wide,a.button.wide{min-width:200px;padding:14px 24px}a.read-more,a.read-more:hover,a.read-more:active{display:inline-flex;background:none;box-shadow:none;padding:0;margin:20px 0;max-width:100%}.code-toolbar{margin-bottom:20px}.code-toolbar .toolbar-item a{position:relative;display:inline-flex;align-items:center;justify-content:center;padding:3px 8px;margin-bottom:5px;text-align:center;font-size:13px;font-weight:500;border-radius:8px;border:1px solid rgba(0,0,0,0);appearance:none;cursor:pointer;outline:none} \ No newline at end of file diff --git a/public/color/background_auto.css b/public/color/background_auto.css new file mode 100644 index 0000000..a14b617 --- /dev/null +++ b/public/color/background_auto.css @@ -0,0 +1 @@ +@media (prefers-color-scheme: light){:root{--background: white;--color: #101010}}@media (prefers-color-scheme: dark){:root{--background: #101010;--color: #A9B7C6}} \ No newline at end of file diff --git a/public/color/background_blue.css b/public/color/background_blue.css new file mode 100644 index 0000000..084eec8 --- /dev/null +++ b/public/color/background_blue.css @@ -0,0 +1 @@ +:root{--background: #1D212C} \ No newline at end of file diff --git a/public/color/background_dark.css b/public/color/background_dark.css new file mode 100644 index 0000000..c1b491b --- /dev/null +++ b/public/color/background_dark.css @@ -0,0 +1 @@ +:root{--background: #101010;--color: #A9B7C6} \ No newline at end of file diff --git a/public/color/background_green.css b/public/color/background_green.css new file mode 100644 index 0000000..de564d5 --- /dev/null +++ b/public/color/background_green.css @@ -0,0 +1 @@ +:root{--background: #1F222A} \ No newline at end of file diff --git a/public/color/background_light.css b/public/color/background_light.css new file mode 100644 index 0000000..ea0bc08 --- /dev/null +++ b/public/color/background_light.css @@ -0,0 +1 @@ +:root{--background: #f0f0f0} \ No newline at end of file diff --git a/public/color/background_orange.css b/public/color/background_orange.css new file mode 100644 index 0000000..8d64140 --- /dev/null +++ b/public/color/background_orange.css @@ -0,0 +1 @@ +:root{--background: #222129} \ No newline at end of file diff --git a/public/color/background_pink.css b/public/color/background_pink.css new file mode 100644 index 0000000..17693cb --- /dev/null +++ b/public/color/background_pink.css @@ -0,0 +1 @@ +:root{--background: #21202C} \ No newline at end of file diff --git a/public/color/background_red.css b/public/color/background_red.css new file mode 100644 index 0000000..3605399 --- /dev/null +++ b/public/color/background_red.css @@ -0,0 +1 @@ +:root{--background: #221F29} \ No newline at end of file diff --git a/public/color/blue-auto.css b/public/color/blue-auto.css new file mode 100644 index 0000000..56ff54f --- /dev/null +++ b/public/color/blue-auto.css @@ -0,0 +1 @@ +@media (prefers-color-scheme: dark){:root{--accent: rgb(35,176,255);--accent-alpha-70: rgba(35,176,255,.7);--accent-alpha-20: rgba(35,176,255,.2);--background: #101010;--color: #f0f0f0;--border-color: rgba(255,240,224,.125)}:root div.logo{color:#000}}@media (prefers-color-scheme: light){:root{--accent: rgb(32,128,192);--accent-alpha-70: rgba(32,128,192,.7);--accent-alpha-20: rgba(32,128,192,.2);--background: white;--color: #201030;--border-color: rgba(0,0,16,.125)}:root div.logo{color:#fff}} \ No newline at end of file diff --git a/public/color/blue-light.css b/public/color/blue-light.css new file mode 100644 index 0000000..2e8deda --- /dev/null +++ b/public/color/blue-light.css @@ -0,0 +1 @@ +:root{--accent: rgb(32,128,192);--accent-alpha-70: rgba(32,128,192,.7);--accent-alpha-20: rgba(32,128,192,.2);--background: white;--color: #1D212C;--border-color: rgba(0, 0, 0, .1)}:root div.logo{color:#fff} \ No newline at end of file diff --git a/public/color/blue.css b/public/color/blue.css new file mode 100644 index 0000000..b5ee951 --- /dev/null +++ b/public/color/blue.css @@ -0,0 +1 @@ +:root{--accent: rgb(35,176,255);--accent-alpha-70: rgba(35,176,255,.7);--accent-alpha-20: rgba(35,176,255,.2);--background: #1D212C;--color: white;--border-color: rgba(255, 255, 255, .1)} \ No newline at end of file diff --git a/public/color/green-auto.css b/public/color/green-auto.css new file mode 100644 index 0000000..e671b44 --- /dev/null +++ b/public/color/green-auto.css @@ -0,0 +1 @@ +@media (prefers-color-scheme: dark){:root{--accent: rgb(120,226,160);--accent-alpha-70: rgba(120,226,160,.7);--accent-alpha-20: rgba(120,226,160,.2);--background: #101010;--color: #f0f0f0;--border-color: rgba(255,240,224,.125)}:root div.logo{color:#000}}@media (prefers-color-scheme: light){:root{--accent: rgb(24, 192, 128);--accent-alpha-70: rgba(24, 192, 128,.7);--accent-alpha-20: rgba(24, 192, 128,.2);--background: white;--color: #201030;--border-color: rgba(0,0,16,.125)}:root div.logo{color:#fff}} \ No newline at end of file diff --git a/public/color/green-light.css b/public/color/green-light.css new file mode 100644 index 0000000..6788de0 --- /dev/null +++ b/public/color/green-light.css @@ -0,0 +1 @@ +:root{--accent: rgb(24, 192, 128);--accent-alpha-70: rgba(24, 192, 128,.7);--accent-alpha-20: rgba(24, 192, 128,.2);--background: white;--color: #1D212C;--border-color: rgba(0, 0, 0, .1)}:root div.logo{color:#fff} \ No newline at end of file diff --git a/public/color/green.css b/public/color/green.css new file mode 100644 index 0000000..e622015 --- /dev/null +++ b/public/color/green.css @@ -0,0 +1 @@ +:root{--accent: rgb(120,226,160);--accent-alpha-70: rgba(120,226,160,.7);--accent-alpha-20: rgba(120,226,160,.2);--background: #1F222A;--color: white;--border-color: rgba(255, 255, 255, .1)} \ No newline at end of file diff --git a/public/color/orange-auto.css b/public/color/orange-auto.css new file mode 100644 index 0000000..50ee1d8 --- /dev/null +++ b/public/color/orange-auto.css @@ -0,0 +1 @@ +@media (prefers-color-scheme: dark){:root{--accent: rgb(255,168,106);--accent-alpha-70: rgba(255,168,106,.7);--accent-alpha-20: rgba(255,168,106,.2);--background: #101010;--color: #f0f0f0;--border-color: rgba(255,240,224,.125)}:root div.logo{color:#000}}@media (prefers-color-scheme: light){:root{--accent: rgb(240,128,48);--accent-alpha-70: rgba(240,128,48,.7);--accent-alpha-20: rgba(240,128,48,.2);--background: white;--color: #201030;--border-color: rgba(0,0,16,.125)}:root div.logo{color:#fff}} \ No newline at end of file diff --git a/public/color/orange-light.css b/public/color/orange-light.css new file mode 100644 index 0000000..979f284 --- /dev/null +++ b/public/color/orange-light.css @@ -0,0 +1 @@ +:root{--accent: rgb(240,128,48);--accent-alpha-70: rgba(240,128,48,.7);--accent-alpha-20: rgba(240,128,48,.2);--background: white;--color: #1D212C;--border-color: rgba(0, 0, 0, .1)}:root div.logo{color:#fff} \ No newline at end of file diff --git a/public/color/orange.css b/public/color/orange.css new file mode 100644 index 0000000..3f1a992 --- /dev/null +++ b/public/color/orange.css @@ -0,0 +1 @@ +:root{--accent: rgb(255,168,106);--accent-alpha-70: rgba(255,168,106,.7);--accent-alpha-20: rgba(255,168,106,.2);--background: #222129;--color: white;--border-color: rgba(255, 255, 255, .1)} \ No newline at end of file diff --git a/public/color/pink-auto.css b/public/color/pink-auto.css new file mode 100644 index 0000000..34df818 --- /dev/null +++ b/public/color/pink-auto.css @@ -0,0 +1 @@ +@media (prefers-color-scheme: dark){:root{--accent: rgb(224,64,192);--accent-alpha-70: rgba(224,64,192);--accent-alpha-20: rgba(224,64,192,.2);--background: #101010;--color: #f0f0f0;--border-color: rgba(255,240,224,.125)}:root div.logo{color:#000}}@media (prefers-color-scheme: light){:root{--accent: rgb(238,114,241);--accent-alpha-70: rgba(238,114,241,.7);--accent-alpha-20: rgba(238,114,241,.2);--background: white;--color: #201030;--border-color: rgba(0,0,16,.125)}:root div.logo{color:#fff}} \ No newline at end of file diff --git a/public/color/pink-light.css b/public/color/pink-light.css new file mode 100644 index 0000000..881f216 --- /dev/null +++ b/public/color/pink-light.css @@ -0,0 +1 @@ +:root{--accent: rgb(224,64,192);--accent-alpha-70: rgba(224,64,192);--accent-alpha-20: rgba(224,64,192,.2);--background: white;--color: #1D212C;--border-color: rgba(0, 0, 0, .1)}:root div.logo{color:#fff} \ No newline at end of file diff --git a/public/color/pink.css b/public/color/pink.css new file mode 100644 index 0000000..f2c4c43 --- /dev/null +++ b/public/color/pink.css @@ -0,0 +1 @@ +:root{--accent: rgb(238,114,241);--accent-alpha-70: rgba(238,114,241,.7);--accent-alpha-20: rgba(238,114,241,.2);--background: #21202C;--color: white;--border-color: rgba(255, 255, 255, .1)} \ No newline at end of file diff --git a/public/color/red-auto.css b/public/color/red-auto.css new file mode 100644 index 0000000..d0c7147 --- /dev/null +++ b/public/color/red-auto.css @@ -0,0 +1 @@ +@media (prefers-color-scheme: dark){:root{--accent: rgb(255,98,102);--accent-alpha-70: rgba(255,98,102,.7);--accent-alpha-20: rgba(255,98,102,.2);--background: #101010;--color: #f0f0f0;--border-color: rgba(255,240,224,.125)}:root div.logo{color:#000}}@media (prefers-color-scheme: light){:root{--accent: rgb(240,48,64);--accent-alpha-70: rgba(240,48,64,.7);--accent-alpha-20: rgba(240,48,64,.2);--background: white;--color: #201030;--border-color: rgba(0,0,16,.125)}:root div.logo{color:#fff}} \ No newline at end of file diff --git a/public/color/red-light.css b/public/color/red-light.css new file mode 100644 index 0000000..a854a79 --- /dev/null +++ b/public/color/red-light.css @@ -0,0 +1 @@ +:root{--accent: rgb(240,48,64);--accent-alpha-70: rgba(240,48,64,.7);--accent-alpha-20: rgba(240,48,64,.2);--background: white;--color: #1D212C;--border-color: rgba(0, 0, 0, .1)}:root div.logo{color:#fff} \ No newline at end of file diff --git a/public/color/red.css b/public/color/red.css new file mode 100644 index 0000000..3b1e34a --- /dev/null +++ b/public/color/red.css @@ -0,0 +1 @@ +:root{--accent: rgb(255,98,102);--accent-alpha-70: rgba(255,98,102,.7);--accent-alpha-20: rgba(255,98,102,.2);--background: #221F29;--color: white;--border-color: rgba(255, 255, 255, .1)} \ No newline at end of file diff --git a/public/css/water.min.css b/public/css/water.min.css new file mode 100644 index 0000000..ff454a6 --- /dev/null +++ b/public/css/water.min.css @@ -0,0 +1 @@ +:root{--background-body:#fff;--background:#efefef;--background-alt:#f7f7f7;--selection:#9e9e9e;--text-main:#363636;--text-bright:#000;--text-muted:#70777f;--links:#0076d1;--focus:rgba(0,150,191,0.67);--border:#dbdbdb;--code:#000;--animation-duration:0.1s;--button-base:#d0cfcf;--button-hover:#9b9b9b;--scrollbar-thumb:#aaa;--scrollbar-thumb-hover:var(--button-hover);--form-placeholder:#949494;--form-text:#1d1d1d;--variable:#39a33c;--highlight:#ff0;--select-arrow:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='63' width='117' fill='%23161f27'%3E%3Cpath d='M115 2c-1-2-4-2-5 0L59 53 7 2a4 4 0 00-5 5l54 54 2 2 3-2 54-54c2-1 2-4 0-5z'/%3E%3C/svg%3E")}@media (prefers-color-scheme: dark){:root{--background-body:#202b38;--background:#161f27;--background-alt:#1a242f;--selection:#1c76c5;--text-main:#dbdbdb;--text-bright:#fff;--text-muted:#a9b1ba;--links:#41adff;--focus:rgba(0,150,191,0.67);--border:#526980;--code:#ffbe85;--animation-duration:0.1s;--button-base:#0c151c;--button-hover:#040a0f;--scrollbar-thumb:var(--button-hover);--scrollbar-thumb-hover:#000;--form-placeholder:#a9a9a9;--form-text:#fff;--variable:#d941e2;--highlight:#efdb43;--select-arrow:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='63' width='117' fill='%23efefef'%3E%3Cpath d='M115 2c-1-2-4-2-5 0L59 53 7 2a4 4 0 00-5 5l54 54 2 2 3-2 54-54c2-1 2-4 0-5z'/%3E%3C/svg%3E")}}html{scrollbar-color:#aaa #fff;scrollbar-color:var(--scrollbar-thumb) var(--background-body);scrollbar-width:thin}@media (prefers-color-scheme: dark){html{scrollbar-color:#040a0f #202b38;scrollbar-color:var(--scrollbar-thumb) var(--background-body)}}body{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,Segoe UI Emoji,Apple Color Emoji,Noto Color Emoji,sans-serif;line-height:1.4;max-width:800px;margin:20px auto;padding:0 10px;word-wrap:break-word;color:#363636;color:var(--text-main);background:#fff;background:var(--background-body);text-rendering:optimizeLegibility}@media (prefers-color-scheme: dark){body{background:#202b38;background:var(--background-body);color:#dbdbdb;color:var(--text-main)}}button{transition:background-color .1s linear,border-color .1s linear,color .1s linear,box-shadow .1s linear,transform .1s ease;transition:background-color var(--animation-duration) linear,border-color var(--animation-duration) linear,color var(--animation-duration) linear,box-shadow var(--animation-duration) linear,transform var(--animation-duration) ease}@media (prefers-color-scheme: dark){button{transition:background-color .1s linear,border-color .1s linear,color .1s linear,box-shadow .1s linear,transform .1s ease;transition:background-color var(--animation-duration) linear,border-color var(--animation-duration) linear,color var(--animation-duration) linear,box-shadow var(--animation-duration) linear,transform var(--animation-duration) ease}}input{transition:background-color .1s linear,border-color .1s linear,color .1s linear,box-shadow .1s linear,transform .1s ease;transition:background-color var(--animation-duration) linear,border-color var(--animation-duration) linear,color var(--animation-duration) linear,box-shadow var(--animation-duration) linear,transform var(--animation-duration) ease}@media (prefers-color-scheme: dark){input{transition:background-color .1s linear,border-color .1s linear,color .1s linear,box-shadow .1s linear,transform .1s ease;transition:background-color var(--animation-duration) linear,border-color var(--animation-duration) linear,color var(--animation-duration) linear,box-shadow var(--animation-duration) linear,transform var(--animation-duration) ease}}textarea{transition:background-color .1s linear,border-color .1s linear,color .1s linear,box-shadow .1s linear,transform .1s ease;transition:background-color var(--animation-duration) linear,border-color var(--animation-duration) linear,color var(--animation-duration) linear,box-shadow var(--animation-duration) linear,transform var(--animation-duration) ease}@media (prefers-color-scheme: dark){textarea{transition:background-color .1s linear,border-color .1s linear,color .1s linear,box-shadow .1s linear,transform .1s ease;transition:background-color var(--animation-duration) linear,border-color var(--animation-duration) linear,color var(--animation-duration) linear,box-shadow var(--animation-duration) linear,transform var(--animation-duration) ease}}h1{font-size:2.2em;margin-top:0}h1,h2,h3,h4,h5,h6{margin-bottom:12px;margin-top:24px}h1{color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){h1{color:#fff;color:var(--text-bright)}}h2{color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){h2{color:#fff;color:var(--text-bright)}}h3{color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){h3{color:#fff;color:var(--text-bright)}}h4{color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){h4{color:#fff;color:var(--text-bright)}}h5{color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){h5{color:#fff;color:var(--text-bright)}}h6{color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){h6{color:#fff;color:var(--text-bright)}}strong{color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){strong{color:#fff;color:var(--text-bright)}}b,h1,h2,h3,h4,h5,h6,strong,th{font-weight:600}q:after,q:before{content:none}blockquote{border-left:4px solid rgba(0,150,191,.67);border-left:4px solid var(--focus);margin:1.5em 0;padding:.5em 1em;font-style:italic}@media (prefers-color-scheme: dark){blockquote{border-left:4px solid rgba(0,150,191,.67);border-left:4px solid var(--focus)}}q{border-left:4px solid rgba(0,150,191,.67);border-left:4px solid var(--focus);margin:1.5em 0;padding:.5em 1em;font-style:italic}@media (prefers-color-scheme: dark){q{border-left:4px solid rgba(0,150,191,.67);border-left:4px solid var(--focus)}}blockquote>footer{font-style:normal;border:0}address,blockquote cite{font-style:normal}a[href^=mailto\:]:before{content:"📧 "}a[href^=tel\:]:before{content:"📞 "}a[href^=sms\:]:before{content:"💬 "}mark{background-color:#ff0;background-color:var(--highlight);border-radius:2px;padding:0 2px;color:#000}@media (prefers-color-scheme: dark){mark{background-color:#efdb43;background-color:var(--highlight)}}a>code,a>strong{color:inherit}button,input[type=button],input[type=checkbox],input[type=radio],input[type=range],input[type=reset],input[type=submit],select{cursor:pointer}input,select{display:block}[type=checkbox],[type=radio]{display:initial}input{color:#1d1d1d;color:var(--form-text);background-color:#efefef;background-color:var(--background);font-family:inherit;font-size:inherit;margin-right:6px;margin-bottom:6px;padding:10px;border:none;border-radius:6px;outline:none}@media (prefers-color-scheme: dark){input{background-color:#161f27;background-color:var(--background);color:#fff;color:var(--form-text)}}button{color:#1d1d1d;color:var(--form-text);background-color:#efefef;background-color:var(--background);font-family:inherit;font-size:inherit;margin-right:6px;margin-bottom:6px;padding:10px;border:none;border-radius:6px;outline:none}@media (prefers-color-scheme: dark){button{background-color:#161f27;background-color:var(--background);color:#fff;color:var(--form-text)}}textarea{color:#1d1d1d;color:var(--form-text);background-color:#efefef;background-color:var(--background);font-family:inherit;font-size:inherit;margin-right:6px;margin-bottom:6px;padding:10px;border:none;border-radius:6px;outline:none}@media (prefers-color-scheme: dark){textarea{background-color:#161f27;background-color:var(--background);color:#fff;color:var(--form-text)}}select{color:#1d1d1d;color:var(--form-text);background-color:#efefef;background-color:var(--background);font-family:inherit;font-size:inherit;margin-right:6px;margin-bottom:6px;padding:10px;border:none;border-radius:6px;outline:none}@media (prefers-color-scheme: dark){select{background-color:#161f27;background-color:var(--background);color:#fff;color:var(--form-text)}}button{background-color:#d0cfcf;background-color:var(--button-base);padding-right:30px;padding-left:30px}@media (prefers-color-scheme: dark){button{background-color:#0c151c;background-color:var(--button-base)}}input[type=submit]{background-color:#d0cfcf;background-color:var(--button-base);padding-right:30px;padding-left:30px}@media (prefers-color-scheme: dark){input[type=submit]{background-color:#0c151c;background-color:var(--button-base)}}input[type=reset]{background-color:#d0cfcf;background-color:var(--button-base);padding-right:30px;padding-left:30px}@media (prefers-color-scheme: dark){input[type=reset]{background-color:#0c151c;background-color:var(--button-base)}}input[type=button]{background-color:#d0cfcf;background-color:var(--button-base);padding-right:30px;padding-left:30px}@media (prefers-color-scheme: dark){input[type=button]{background-color:#0c151c;background-color:var(--button-base)}}button:hover{background:#9b9b9b;background:var(--button-hover)}@media (prefers-color-scheme: dark){button:hover{background:#040a0f;background:var(--button-hover)}}input[type=submit]:hover{background:#9b9b9b;background:var(--button-hover)}@media (prefers-color-scheme: dark){input[type=submit]:hover{background:#040a0f;background:var(--button-hover)}}input[type=reset]:hover{background:#9b9b9b;background:var(--button-hover)}@media (prefers-color-scheme: dark){input[type=reset]:hover{background:#040a0f;background:var(--button-hover)}}input[type=button]:hover{background:#9b9b9b;background:var(--button-hover)}@media (prefers-color-scheme: dark){input[type=button]:hover{background:#040a0f;background:var(--button-hover)}}input[type=color]{min-height:2rem;padding:8px;cursor:pointer}input[type=checkbox],input[type=radio]{height:1em;width:1em}input[type=radio]{border-radius:100%}input{vertical-align:top}label{vertical-align:middle;margin-bottom:4px;display:inline-block}button,input:not([type=checkbox]):not([type=radio]),input[type=range],select,textarea{-webkit-appearance:none}textarea{display:block;margin-right:0;box-sizing:border-box;resize:vertical}textarea:not([cols]){width:100%}textarea:not([rows]){min-height:40px;height:140px}select{background:#efefef url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='63' width='117' fill='%23161f27'%3E%3Cpath d='M115 2c-1-2-4-2-5 0L59 53 7 2a4 4 0 00-5 5l54 54 2 2 3-2 54-54c2-1 2-4 0-5z'/%3E%3C/svg%3E") calc(100% - 12px) 50%/12px no-repeat;background:var(--background) var(--select-arrow) calc(100% - 12px) 50%/12px no-repeat;padding-right:35px}@media (prefers-color-scheme: dark){select{background:#161f27 url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='63' width='117' fill='%23efefef'%3E%3Cpath d='M115 2c-1-2-4-2-5 0L59 53 7 2a4 4 0 00-5 5l54 54 2 2 3-2 54-54c2-1 2-4 0-5z'/%3E%3C/svg%3E") calc(100% - 12px) 50%/12px no-repeat;background:var(--background) var(--select-arrow) calc(100% - 12px) 50%/12px no-repeat}}select::-ms-expand{display:none}select[multiple]{padding-right:10px;background-image:none;overflow-y:auto}input:focus{box-shadow:0 0 0 2px rgba(0,150,191,.67);box-shadow:0 0 0 2px var(--focus)}@media (prefers-color-scheme: dark){input:focus{box-shadow:0 0 0 2px rgba(0,150,191,.67);box-shadow:0 0 0 2px var(--focus)}}select:focus{box-shadow:0 0 0 2px rgba(0,150,191,.67);box-shadow:0 0 0 2px var(--focus)}@media (prefers-color-scheme: dark){select:focus{box-shadow:0 0 0 2px rgba(0,150,191,.67);box-shadow:0 0 0 2px var(--focus)}}button:focus{box-shadow:0 0 0 2px rgba(0,150,191,.67);box-shadow:0 0 0 2px var(--focus)}@media (prefers-color-scheme: dark){button:focus{box-shadow:0 0 0 2px rgba(0,150,191,.67);box-shadow:0 0 0 2px var(--focus)}}textarea:focus{box-shadow:0 0 0 2px rgba(0,150,191,.67);box-shadow:0 0 0 2px var(--focus)}@media (prefers-color-scheme: dark){textarea:focus{box-shadow:0 0 0 2px rgba(0,150,191,.67);box-shadow:0 0 0 2px var(--focus)}}button:active,input[type=button]:active,input[type=checkbox]:active,input[type=radio]:active,input[type=range]:active,input[type=reset]:active,input[type=submit]:active{transform:translateY(2px)}button:disabled,input:disabled,select:disabled,textarea:disabled{cursor:not-allowed;opacity:.5}::-moz-placeholder{color:#949494;color:var(--form-placeholder)}:-ms-input-placeholder{color:#949494;color:var(--form-placeholder)}::-ms-input-placeholder{color:#949494;color:var(--form-placeholder)}::placeholder{color:#949494;color:var(--form-placeholder)}@media (prefers-color-scheme: dark){::-moz-placeholder{color:#a9a9a9;color:var(--form-placeholder)}:-ms-input-placeholder{color:#a9a9a9;color:var(--form-placeholder)}::-ms-input-placeholder{color:#a9a9a9;color:var(--form-placeholder)}::placeholder{color:#a9a9a9;color:var(--form-placeholder)}}fieldset{border:1px solid rgba(0,150,191,.67);border:1px solid var(--focus);border-radius:6px;margin:0 0 12px;padding:10px}@media (prefers-color-scheme: dark){fieldset{border:1px solid rgba(0,150,191,.67);border:1px solid var(--focus)}}legend{font-size:.9em;font-weight:600}input[type=range]{margin:10px 0;padding:10px 0;background:rgba(0,0,0,0)}input[type=range]:focus{outline:none}input[type=range]::-webkit-slider-runnable-track{width:100%;height:9.5px;-webkit-transition:.2s;transition:.2s;background:#efefef;background:var(--background);border-radius:3px}@media (prefers-color-scheme: dark){input[type=range]::-webkit-slider-runnable-track{background:#161f27;background:var(--background)}}input[type=range]::-webkit-slider-thumb{box-shadow:0 1px 1px #000,0 0 1px #0d0d0d;height:20px;width:20px;border-radius:50%;background:#dbdbdb;background:var(--border);-webkit-appearance:none;margin-top:-7px}@media (prefers-color-scheme: dark){input[type=range]::-webkit-slider-thumb{background:#526980;background:var(--border)}}input[type=range]:focus::-webkit-slider-runnable-track{background:#efefef;background:var(--background)}@media (prefers-color-scheme: dark){input[type=range]:focus::-webkit-slider-runnable-track{background:#161f27;background:var(--background)}}input[type=range]::-moz-range-track{width:100%;height:9.5px;-moz-transition:.2s;transition:.2s;background:#efefef;background:var(--background);border-radius:3px}@media (prefers-color-scheme: dark){input[type=range]::-moz-range-track{background:#161f27;background:var(--background)}}input[type=range]::-moz-range-thumb{box-shadow:1px 1px 1px #000,0 0 1px #0d0d0d;height:20px;width:20px;border-radius:50%;background:#dbdbdb;background:var(--border)}@media (prefers-color-scheme: dark){input[type=range]::-moz-range-thumb{background:#526980;background:var(--border)}}input[type=range]::-ms-track{width:100%;height:9.5px;background:rgba(0,0,0,0);border-color:rgba(0,0,0,0);border-width:16px 0;color:rgba(0,0,0,0)}input[type=range]::-ms-fill-lower{background:#efefef;background:var(--background);border:.2px solid #010101;border-radius:3px;box-shadow:1px 1px 1px #000,0 0 1px #0d0d0d}@media (prefers-color-scheme: dark){input[type=range]::-ms-fill-lower{background:#161f27;background:var(--background)}}input[type=range]::-ms-fill-upper{background:#efefef;background:var(--background);border:.2px solid #010101;border-radius:3px;box-shadow:1px 1px 1px #000,0 0 1px #0d0d0d}@media (prefers-color-scheme: dark){input[type=range]::-ms-fill-upper{background:#161f27;background:var(--background)}}input[type=range]::-ms-thumb{box-shadow:1px 1px 1px #000,0 0 1px #0d0d0d;border:1px solid #000;height:20px;width:20px;border-radius:50%;background:#dbdbdb;background:var(--border)}@media (prefers-color-scheme: dark){input[type=range]::-ms-thumb{background:#526980;background:var(--border)}}input[type=range]:focus::-ms-fill-lower{background:#efefef;background:var(--background)}@media (prefers-color-scheme: dark){input[type=range]:focus::-ms-fill-lower{background:#161f27;background:var(--background)}}input[type=range]:focus::-ms-fill-upper{background:#efefef;background:var(--background)}@media (prefers-color-scheme: dark){input[type=range]:focus::-ms-fill-upper{background:#161f27;background:var(--background)}}a{text-decoration:none;color:#0076d1;color:var(--links)}@media (prefers-color-scheme: dark){a{color:#41adff;color:var(--links)}}a:hover{text-decoration:underline}code{background:#efefef;background:var(--background);color:#000;color:var(--code);padding:2.5px 5px;border-radius:6px;font-size:1em}@media (prefers-color-scheme: dark){code{color:#ffbe85;color:var(--code);background:#161f27;background:var(--background)}}samp{background:#efefef;background:var(--background);color:#000;color:var(--code);padding:2.5px 5px;border-radius:6px;font-size:1em}@media (prefers-color-scheme: dark){samp{color:#ffbe85;color:var(--code);background:#161f27;background:var(--background)}}time{background:#efefef;background:var(--background);color:#000;color:var(--code);padding:2.5px 5px;border-radius:6px;font-size:1em}@media (prefers-color-scheme: dark){time{color:#ffbe85;color:var(--code);background:#161f27;background:var(--background)}}pre>code{padding:10px;display:block;overflow-x:auto}var{color:#39a33c;color:var(--variable);font-style:normal;font-family:monospace}@media (prefers-color-scheme: dark){var{color:#d941e2;color:var(--variable)}}kbd{background:#efefef;background:var(--background);border:1px solid #dbdbdb;border:1px solid var(--border);border-radius:2px;color:#363636;color:var(--text-main);padding:2px 4px}@media (prefers-color-scheme: dark){kbd{color:#dbdbdb;color:var(--text-main);border:1px solid #526980;border:1px solid var(--border);background:#161f27;background:var(--background)}}img,video{max-width:100%;height:auto}hr{border:none;border-top:1px solid #dbdbdb;border-top:1px solid var(--border)}@media (prefers-color-scheme: dark){hr{border-top:1px solid #526980;border-top:1px solid var(--border)}}table{border-collapse:collapse;margin-bottom:10px;width:100%;table-layout:fixed}table caption,td,th{text-align:left}td,th{padding:6px;vertical-align:top;word-wrap:break-word}thead{border-bottom:1px solid #dbdbdb;border-bottom:1px solid var(--border)}@media (prefers-color-scheme: dark){thead{border-bottom:1px solid #526980;border-bottom:1px solid var(--border)}}tfoot{border-top:1px solid #dbdbdb;border-top:1px solid var(--border)}@media (prefers-color-scheme: dark){tfoot{border-top:1px solid #526980;border-top:1px solid var(--border)}}tbody tr:nth-child(2n){background-color:#efefef;background-color:var(--background)}@media (prefers-color-scheme: dark){tbody tr:nth-child(2n){background-color:#161f27;background-color:var(--background)}}tbody tr:nth-child(2n) button{background-color:#f7f7f7;background-color:var(--background-alt)}@media (prefers-color-scheme: dark){tbody tr:nth-child(2n) button{background-color:#1a242f;background-color:var(--background-alt)}}tbody tr:nth-child(2n) button:hover{background-color:#fff;background-color:var(--background-body)}@media (prefers-color-scheme: dark){tbody tr:nth-child(2n) button:hover{background-color:#202b38;background-color:var(--background-body)}}::-webkit-scrollbar{height:10px;width:10px}::-webkit-scrollbar-track{background:#efefef;background:var(--background);border-radius:6px}@media (prefers-color-scheme: dark){::-webkit-scrollbar-track{background:#161f27;background:var(--background)}}::-webkit-scrollbar-thumb{background:#aaa;background:var(--scrollbar-thumb);border-radius:6px}@media (prefers-color-scheme: dark){::-webkit-scrollbar-thumb{background:#040a0f;background:var(--scrollbar-thumb)}}::-webkit-scrollbar-thumb:hover{background:#9b9b9b;background:var(--scrollbar-thumb-hover)}@media (prefers-color-scheme: dark){::-webkit-scrollbar-thumb:hover{background:#000;background:var(--scrollbar-thumb-hover)}}::-moz-selection{background-color:#9e9e9e;background-color:var(--selection);color:#000;color:var(--text-bright)}::selection{background-color:#9e9e9e;background-color:var(--selection);color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){::-moz-selection{color:#fff;color:var(--text-bright)}::selection{color:#fff;color:var(--text-bright)}}@media (prefers-color-scheme: dark){::-moz-selection{background-color:#1c76c5;background-color:var(--selection)}::selection{background-color:#1c76c5;background-color:var(--selection)}}details{display:flex;flex-direction:column;align-items:flex-start;background-color:#f7f7f7;background-color:var(--background-alt);padding:10px 10px 0;margin:1em 0;border-radius:6px;overflow:hidden}@media (prefers-color-scheme: dark){details{background-color:#1a242f;background-color:var(--background-alt)}}details[open]{padding:10px}details>:last-child{margin-bottom:0}details[open] summary{margin-bottom:10px}summary{display:list-item;background-color:#efefef;background-color:var(--background);padding:10px;margin:-10px -10px 0;cursor:pointer;outline:none}@media (prefers-color-scheme: dark){summary{background-color:#161f27;background-color:var(--background)}}summary:focus,summary:hover{text-decoration:underline}details>:not(summary){margin-top:0}summary::-webkit-details-marker{color:#363636;color:var(--text-main)}@media (prefers-color-scheme: dark){summary::-webkit-details-marker{color:#dbdbdb;color:var(--text-main)}}dialog{background-color:#f7f7f7;background-color:var(--background-alt);color:#363636;color:var(--text-main);border-radius:6px;border:#dbdbdb;border-color:var(--border);padding:10px 30px}@media (prefers-color-scheme: dark){dialog{border-color:#526980;border-color:var(--border);color:#dbdbdb;color:var(--text-main);background-color:#1a242f;background-color:var(--background-alt)}}dialog>header:first-child{background-color:#efefef;background-color:var(--background);border-radius:6px 6px 0 0;margin:-10px -30px 10px;padding:10px;text-align:center}@media (prefers-color-scheme: dark){dialog>header:first-child{background-color:#161f27;background-color:var(--background)}}dialog::-webkit-backdrop{background:rgba(0,0,0,.61);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}dialog::backdrop{background:rgba(0,0,0,.61);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}footer{border-top:1px solid #dbdbdb;border-top:1px solid var(--border);padding-top:10px;color:#70777f;color:var(--text-muted)}@media (prefers-color-scheme: dark){footer{color:#a9b1ba;color:var(--text-muted);border-top:1px solid #526980;border-top:1px solid var(--border)}}body>footer{margin-top:40px}@media print{body,button,code,details,input,pre,summary,textarea{background-color:#fff}button,input,textarea{border:1px solid #000}body,button,code,footer,h1,h2,h3,h4,h5,h6,input,pre,strong,summary,textarea{color:#000}summary::marker{color:#000}summary::-webkit-details-marker{color:#000}tbody tr:nth-child(2n){background-color:#f2f2f2}a{color:blue;text-decoration:underline}} \ No newline at end of file diff --git a/public/dich.webp b/public/dich.webp new file mode 100644 index 0000000..c33f06f Binary files /dev/null and b/public/dich.webp differ diff --git a/public/font-hack-subset.css b/public/font-hack-subset.css new file mode 100644 index 0000000..2707279 --- /dev/null +++ b/public/font-hack-subset.css @@ -0,0 +1,4 @@ +/*! + * Hack typeface https://github.com/source-foundry/Hack + * License: https://github.com/source-foundry/Hack/blob/master/LICENSE.md + */@font-face{font-family:"Hack";src:url("fonts/hack-regular.woff2?sha=3114f1256") format("woff2"),url("fonts/hack-regular.woff?sha=3114f1256") format("woff");font-weight:400;font-style:normal}@font-face{font-family:"Hack";src:url("fonts/hack-bold-subset.woff2?sha=3114f1256") format("woff2"),url("fonts/hack-bold-subset.woff?sha=3114f1256") format("woff");font-weight:700;font-style:normal}@font-face{font-family:"Hack";src:url("fonts/hack-italic-subset.woff2?sha=3114f1256") format("woff2"),url("fonts/hack-italic-webfont.woff?sha=3114f1256") format("woff");font-weight:400;font-style:italic}@font-face{font-family:"Hack";src:url("fonts/hack-bolditalic-subset.woff2?sha=3114f1256") format("woff2"),url("fonts/hack-bolditalic-subset.woff?sha=3114f1256") format("woff");font-weight:700;font-style:italic} \ No newline at end of file diff --git a/public/font-hack.css b/public/font-hack.css new file mode 100644 index 0000000..2a0205d --- /dev/null +++ b/public/font-hack.css @@ -0,0 +1,4 @@ +/*! + * Hack typeface https://github.com/source-foundry/Hack + * License: https://github.com/source-foundry/Hack/blob/master/LICENSE.md + */@font-face{font-family:"Hack";src:url("fonts/hack-regular.woff2?sha=3114f1256") format("woff2"),url("fonts/hack-regular.woff?sha=3114f1256") format("woff");font-weight:400;font-style:normal}@font-face{font-family:"Hack";src:url("fonts/hack-bold.woff2?sha=3114f1256") format("woff2"),url("fonts/hack-bold.woff?sha=3114f1256") format("woff");font-weight:700;font-style:normal}@font-face{font-family:"Hack";src:url("fonts/hack-italic.woff2?sha=3114f1256") format("woff2"),url("fonts/hack-italic.woff?sha=3114f1256") format("woff");font-weight:400;font-style:italic}@font-face{font-family:"Hack";src:url("fonts/hack-bolditalic.woff2?sha=3114f1256") format("woff2"),url("fonts/hack-bolditalic.woff?sha=3114f1256") format("woff");font-weight:700;font-style:italic} \ No newline at end of file diff --git a/public/fonts/hack-bold-subset.woff b/public/fonts/hack-bold-subset.woff new file mode 100644 index 0000000..a47c8aa Binary files /dev/null and b/public/fonts/hack-bold-subset.woff differ diff --git a/public/fonts/hack-bold-subset.woff2 b/public/fonts/hack-bold-subset.woff2 new file mode 100644 index 0000000..93d425e Binary files /dev/null and b/public/fonts/hack-bold-subset.woff2 differ diff --git a/public/fonts/hack-bold.woff b/public/fonts/hack-bold.woff new file mode 100644 index 0000000..368b913 Binary files /dev/null and b/public/fonts/hack-bold.woff differ diff --git a/public/fonts/hack-bold.woff2 b/public/fonts/hack-bold.woff2 new file mode 100644 index 0000000..1155477 Binary files /dev/null and b/public/fonts/hack-bold.woff2 differ diff --git a/public/fonts/hack-bolditalic-subset.woff b/public/fonts/hack-bolditalic-subset.woff new file mode 100644 index 0000000..0da4750 Binary files /dev/null and b/public/fonts/hack-bolditalic-subset.woff differ diff --git a/public/fonts/hack-bolditalic-subset.woff2 b/public/fonts/hack-bolditalic-subset.woff2 new file mode 100644 index 0000000..236b7de Binary files /dev/null and b/public/fonts/hack-bolditalic-subset.woff2 differ diff --git a/public/fonts/hack-bolditalic.woff b/public/fonts/hack-bolditalic.woff new file mode 100644 index 0000000..ce87fe2 Binary files /dev/null and b/public/fonts/hack-bolditalic.woff differ diff --git a/public/fonts/hack-bolditalic.woff2 b/public/fonts/hack-bolditalic.woff2 new file mode 100644 index 0000000..46ff1c4 Binary files /dev/null and b/public/fonts/hack-bolditalic.woff2 differ diff --git a/public/fonts/hack-italic-subset.woff b/public/fonts/hack-italic-subset.woff new file mode 100644 index 0000000..1d1f511 Binary files /dev/null and b/public/fonts/hack-italic-subset.woff differ diff --git a/public/fonts/hack-italic-subset.woff2 b/public/fonts/hack-italic-subset.woff2 new file mode 100644 index 0000000..b6f5fc9 Binary files /dev/null and b/public/fonts/hack-italic-subset.woff2 differ diff --git a/public/fonts/hack-italic.woff b/public/fonts/hack-italic.woff new file mode 100644 index 0000000..bd545e4 Binary files /dev/null and b/public/fonts/hack-italic.woff differ diff --git a/public/fonts/hack-italic.woff2 b/public/fonts/hack-italic.woff2 new file mode 100644 index 0000000..1e7630c Binary files /dev/null and b/public/fonts/hack-italic.woff2 differ diff --git a/public/fonts/hack-regular-subset.woff b/public/fonts/hack-regular-subset.woff new file mode 100644 index 0000000..85583a5 Binary files /dev/null and b/public/fonts/hack-regular-subset.woff differ diff --git a/public/fonts/hack-regular-subset.woff2 b/public/fonts/hack-regular-subset.woff2 new file mode 100644 index 0000000..1e3abb9 Binary files /dev/null and b/public/fonts/hack-regular-subset.woff2 differ diff --git a/public/fonts/hack-regular.woff b/public/fonts/hack-regular.woff new file mode 100644 index 0000000..e835381 Binary files /dev/null and b/public/fonts/hack-regular.woff differ diff --git a/public/fonts/hack-regular.woff2 b/public/fonts/hack-regular.woff2 new file mode 100644 index 0000000..524465c Binary files /dev/null and b/public/fonts/hack-regular.woff2 differ diff --git a/public/footer.css b/public/footer.css new file mode 100644 index 0000000..435ff7b --- /dev/null +++ b/public/footer.css @@ -0,0 +1 @@ +.footer{padding:40px 0;flex-grow:0;opacity:.5}.footer__inner{display:flex;align-items:center;justify-content:space-between;margin:0;width:760px;max-width:100%}@media (max-width: 899px){.footer__inner{flex-direction:column}}.footer a{color:inherit}.footer .copyright{display:flex;flex-direction:row;align-items:center;font-size:1rem;color:var(--light-color-secondary)}.footer .copyright--user{margin:auto;text-align:center}.footer .copyright>*:first-child:not(:only-child){margin-right:10px}@media (max-width: 899px){.footer .copyright>*:first-child:not(:only-child){border:none;padding:0;margin:0}}@media (max-width: 899px){.footer .copyright{flex-direction:column;margin-top:10px}}@media (max-width: 899px){.footer .copyright-theme-sep{display:none}}@media (max-width: 899px){.footer .copyright-theme{font-size:.75rem}} \ No newline at end of file diff --git a/public/header.css b/public/header.css new file mode 100644 index 0000000..8961941 --- /dev/null +++ b/public/header.css @@ -0,0 +1 @@ +.header{display:flex;flex-direction:column;position:relative}.header__inner{display:flex;align-items:center;justify-content:space-between}.header__logo{display:flex;flex:1}.header__logo:after{content:"";background:repeating-linear-gradient(90deg, var(--accent), var(--accent) 2px, rgba(0,0,0,0) 0, rgba(0,0,0,0) 16px);display:block;width:100%;right:10px}.header__logo a{flex:0 0 auto;max-width:100%}.header .menu{margin:20px 0}.header .menu__inner{display:flex;flex-wrap:wrap;list-style:none;margin:0;padding:0}.header .menu__inner li.active{color:var(--accent-alpha-70)}.header .menu__inner li:not(:last-of-type){margin-right:20px;margin-bottom:10px;flex:0 0 auto}.header .menu__sub-inner{position:relative;list-style:none;padding:0;margin:0}.header .menu__sub-inner:not(:only-child){margin-left:20px}.header .menu__sub-inner-more{position:absolute;background:var(--background);box-shadow:var(--shadow);color:#fff;border:2px solid;margin:0;padding:10px;list-style:none;z-index:99;top:35px;left:0}.header .menu__sub-inner-more-trigger{color:var(--accent);user-select:none;cursor:pointer}.header .menu__sub-inner-more li{margin:0;padding:5px;white-space:nowrap} \ No newline at end of file diff --git a/public/images/desktop.png b/public/images/desktop.png new file mode 100644 index 0000000..ca22a0d Binary files /dev/null and b/public/images/desktop.png differ diff --git a/public/images/file.png b/public/images/file.png new file mode 100644 index 0000000..64fd51a Binary files /dev/null and b/public/images/file.png differ diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..eb16a10 --- /dev/null +++ b/public/index.html @@ -0,0 +1,301 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+
+ +

乱七八糟:GPG使用小记

+ + + + + + + + +
+

前言 PGP/GPG 的核心功能——公钥加密、数字签名、信任管理广泛用于各个行业,本文简单说明了其使用方法。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:Baci实验笔记

+ + + + + + + + +
+

前言 ​BACI是一个简化的并发程序模拟器,这里对其语法与运行环境进行说明。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:lazyvim快速上手

+ + + + + + + + +
+

前言 ​LazyVim 是一个基于 Neovim 的现代化配置框架,易于定制和扩展,这里对其介绍并说明使用方法。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:Aria2各平台使用指南

+ + + + + + + + +
+

前言 Aria2是一款开源、跨平台的命令行界面下载管理器,常常被各种下载器软件使用。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:Markdown使用快速教程

+ + + + + + + + +
+

前言 本文为 Markdown 教程,内容涵盖 Markdown 的历史、作用、基本语法和显示效果,可以在github将本文的源码拷贝供大家参考和学习。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +
+ + + + +
+ + + diff --git a/public/learn-linux-for-pc-1/index.html b/public/learn-linux-for-pc-1/index.html new file mode 100644 index 0000000..905cfce --- /dev/null +++ b/public/learn-linux-for-pc-1/index.html @@ -0,0 +1,264 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

Linux之旅(一):构成与发行版

+ + + + + + +
+

前言 Linux 作为一款强大、灵活且免费的操作系统,吸引了越来越多的用户。然而,对于初学者来说,Linux 可能显得有些陌生,甚至有些令人望而生畏。本文旨在为那些刚踏入 Linux 世界的新手提供一份指南,帮助他们更好地了解、使用这个令人着迷的操作系统。我们将探讨Linux的基本概念,解释为何选择Linux,深入剖析其主要构成要素以及不同的发行版之间的差异。

+

一.什么是Linux?

+

Linux 是一种开源的类 UNIX 操作系统内核。它由芬兰的 Linus Torvalds 于1991年开始开发,是一个自由、免费的操作系统。Linux 内核是操作系统的核心,负责管理硬件资源,并提供各种系统服务。与 Windows 和 macOS 等操作系统不同,Linux 的源代码对所有人开放,任何人都可以查看、修改和重新分发。这使得 Linux 具有极高的自由度和可定制性,用户可以根据自己的需求和偏好来定制操作系统。Linux 广泛应用于各种设备,包括个人计算机、服务器、手机、嵌入式系统等,是一个功能强大且灵活多样的操作系统。

+

二.为什么要用Linux?

+
    +
  1. +

    开源免费:Linux 是完全开源的,用户可以免费使用和修改源代码。

    +
  2. +
  3. +

    稳定性和安全性:Linux 系统以其稳定性和安全性而闻名,适合长时间运行的服务。

    +
  4. +
  5. +

    灵活性和可定制性:用户可以根据需要定制 Linux 系统。

    +
  6. +
  7. +

    广泛的软件支持:有大量的开源软件可供选择,满足不同需求。

    +
  8. +
+
+

Liunx可以用来玩游戏吗? +实际上著名的 Steam Deck 的系统就是基于Arch linux 的。对于个人使用而言,现在有不少原生支持linux 的游戏;也可以使用Wine来运行Windows下的游戏。

+
+
+

Linux上软件会不会太少? +参见 常用跨平台开源软件一文,在社区的努力下如今软件生态已经非常丰富,你也可以使用如Flatpak等商店安装软件,或者直接使用Wine。如果有不得不在Windows下使用的软件,可以装双系统。

+
+

三.Linux的主要构成

+

Linux操作系统主要由以下几个部分组成:

+
    +
  1. +

    内核:操作系统的核心,负责管理系统资源。如Zen内核,LTS内核等。

    +
  2. +
  3. +

    Shell:命令行界面,用户通过它与系统交互,如Bash,Zsh等。

    +
  4. +
  5. +

    图形用户界面(GUI):提供图形化操作界面,如GNOME、KDE、XFCE等。

    +
  6. +
  7. +

    文件系统:如ext4、Btrfs等,用于组织和管理磁盘上的文件。

    +
  8. +
  9. +

    系统库:为应用程序提供运行时支持。

    +
  10. +
  11. +

    应用程序:用户可以直接使用的软件,如文本编辑器、网页浏览器等。其中也有著名的GNU工具,如Vim,GCC等。

    +
  12. +
+

四.选择Linux发行版

+

从上文可以发现,选择Linux发行版实际上是在选择 内核/包管理器/图形界面 等组件的排列组合。其中最主要的因素是包管理器。

+

Linux有许多不同的发行版,但大致可以分为几个系:

+

Debian系: +Debian:Debian以稳定性,安全性和轻量级著称,适合用于服务器和桌面环境。我们常说的Ubuntu就是基于Debian的发行版,注重用户友好性和易用性。它提供了多种桌面环境选择,以及许多现成的软件包。

+
APT(Advanced Package Tool)是Debian系发行版的主要包管理器。它使用命令行工具如apt-get、aptitude等来管理软件包。
+
+

Red Hat系:

+
    +
  • Red Hat Enterprise Linux(RHEL):RHEL是一款商业发行版,专注于企业级应用和支持。它提供了长期支持和专业技术支持服务,适用于企业级服务器和工作站。
  • +
  • CentOS:CentOS是基于RHEL源代码编译而成的免费发行版,与RHEL兼容并提供类似的功能和性能。它也提供了长期支持版本和稳定性较高的特点。
  • +
  • Fedora:Fedora是由Red Hat支持的社区驱动的发行版,注重提供最新的软件特性和技术。它适用于开发者和技术爱好者,提供了稳定的发布周期和丰富的软件包。
  • +
+
YUM(Yellowdog Updater, Modified)是Red Hat系发行版的主要包管理器。最近的版本也开始采用DNF(Dandified YUM)。
+
+

Arch系: +Arch Linux:Arch Linux是一个简洁、轻量级且灵活的发行版,注重简洁性和滚动更新。它采用“滚动发布”的方式,用户可以通过自定义安装来构建自己的系统,适合有一定Linux经验的用户。

+
Pacman(Package Manager)是Arch Linux的主要包管理器。它使用简洁的命令来管理软件包,如pacman -S安装软件包、pacman -Syu更新系统等。
+
+

Gentoo系: +Gentoo:Gentoo是一个源码驱动的发行版,用户可以通过源代码自定义编译软件包以满足自己的需求。它注重性能和灵活性,适合高级用户和技术爱好者。

+
Portage是Gentoo的包管理器,它是一个源代码驱动的包管理器,允许用户从源代码构建和安装软件包。
+
+

除了以上列举的包管理器外,还有其他一些较为特殊的包管理器,如Slackware系的pkgtool、SUSE系的zypper等。

+

对于个人使用而言,我个人建议新手使用Ubuntu,有比较易用的界面和完善的资料参考;如果你是一个系统极客,可以使用Arch linux 或者 NixOS。

+

五.个人日常使用需要注意什么?

+
    +
  1. +

    学习命令行:命令行是Linux的强大工具,学习基本命令可以提高效率。

    +
  2. +
  3. +

    选择合适的发行版:根据个人需求和技术水平选择适合的发行版。

    +
  4. +
  5. +

    系统备份:定期备份重要数据,以防意外丢失。

    +
  6. +
  7. +

    软件管理:了解如何安装、更新和卸载软件。

    +
  8. +
  9. +

    安全设置:设置强密码,定期更新系统以修复安全漏洞。

    +
  10. +
  11. +

    社区参与:Linux社区非常活跃,遇到问题可以寻求社区帮助。

    +
  12. +
  13. +

    硬件兼容性:检查你的硬件是否与选择的Linux发行版兼容。

    +
  14. +
  15. +

    驱动程序:确保你的硬件设备有可用的驱动程序,以避免兼容性问题。

    +
  16. +
+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/learn-linux-for-pc-2/index.html b/public/learn-linux-for-pc-2/index.html new file mode 100644 index 0000000..02ded4d --- /dev/null +++ b/public/learn-linux-for-pc-2/index.html @@ -0,0 +1,282 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

Linux之旅(二):FHS与目录结构

+ + + + + + +
+

前言 在Linux世界中,Filesystem Hierarchy Standard(FHS)是一座引导我们进入系统核心的桥梁,它定义了Linux系统中目录结构的规范与作用,为我们提供了一张清晰的地图,指引我们轻松管理和理解系统。本文将深入探讨FHS规范与Linux系统目录结构,解释各个目录的用途与功能,帮助我们更好地理解和利用Linux系统。

+

一.认识FHS

+

FHS是Filesystem Hierarchy Standard(文件系统层次结构标准)的缩写。它是一个定义了Linux系统中目录结构和各个目录作用的规范。FHS规定了Linux系统中各个目录的用途和预期内容,以便确保不同Linux发行版之间的兼容性,并使得用户能够更轻松地理解和管理系统。

+

FHS规范最初由Linux基金会(Linux Foundation)和自由软件基金会(Free Software Foundation)共同发布,并经过多次修订和更新。该规范不仅对Linux系统本身有用,也适用于其他类UNIX操作系统。

+

FHS规范定义了一些基本的目录,如/bin、/boot、/dev等,并规定了每个目录的作用和预期内容。这样做有助于系统管理员和开发人员更好地组织和管理文件系统,并使得用户能够更轻松地找到所需的文件和数据。

+

二.常见目录结构

+

在刚刚由Windows切换至Linux时,往往会对目录感到不解,不知道安装的软件放在哪个目录之下?

+

以下是对Linux系统目录结构的详细说明:

+
    +
  • /(根目录): +根目录是整个文件系统的起点,包含了系统中所有其他目录和文件。在Linux系统中,根目录被表示为/。
  • +
  • /bin(二进制文件): +/bin目录存放着一些最基本的系统命令,如ls、cp、mv等,这些命令通常被所有用户使用。
  • +
  • /boot(引导文件): +/boot目录存放着启动Linux系统所需的引导文件,如内核映像(vmlinuz)、引导加载程序(boot loader)配置文件(如GRUB配置文件)等。
  • +
  • /dev(设备文件): +/dev目录包含了系统中所有设备的特殊文件,如硬盘、键盘、鼠标等。在Linux中,一切皆文件,设备被抽象为文件,通过/dev目录中的特殊文件来表示。
  • +
  • /etc(配置文件): +/etc目录包含了系统的配置文件,如网络配置、用户账户信息、服务配置等。这些配置文件通常以纯文本的形式存在,可以由系统管理员进行编辑和修改。
  • +
  • /home(用户主目录): +/home目录是系统中所有普通用户的主目录所在地,每个用户通常都有一个对应的子目录,用于存放用户的个人文件和数据。
  • +
  • /lib(库文件): +/lib目录存放着系统所需的共享库文件,这些库文件包含了一些程序运行所需的函数和数据,为程序提供了基本的支持。
  • +
  • /mnt(挂载点): +/mnt目录用于挂载临时文件系统,如光盘、移动硬盘等。系统管理员可以将其他设备或文件系统挂载到/mnt目录下,以便访问其中的文件和数据。
  • +
  • /opt(可选软件包): +/opt目录用于存放一些可选的软件包和应用程序,这些软件包通常不属于Linux发行版的默认安装范围,但可以被用户自行安装和管理。
  • +
  • /proc(进程信息): +/proc目录是一个虚拟的文件系统,包含了系统运行时的各种进程信息和系统状态信息。用户可以通过读取/proc目录中的特殊文件来获取系统信息。
  • +
  • /sbin(系统命令): +/sbin目录存放着一些系统管理和维护命令,这些命令通常只能由超级用户(root)执行,用于系统的管理和维护。
  • +
  • /srv(服务数据): +/srv目录用于存放一些服务相关的数据文件,如Web服务器的网站数据、FTP服务器的文件等。每个服务通常都会有一个对应的子目录。
  • +
  • /tmp(临时文件): +/tmp目录用于存放临时文件和临时数据,这些文件通常在系统重启时会被删除。任何用户都可以在/tmp目录下创建临时文件。
  • +
  • /usr(用户程序): +/usr目录包含了系统中大部分用户可用的程序和文件,如用户应用程序、共享库文件、文档等。它通常是系统的二级目录,类似于Windows系统中的Program Files目录。
  • +
  • /var(可变数据): +/var目录用于存放系统运行时产生的可变数据,如日志文件、邮件、缓存文件等。这些数据通常会随着系统的运行而不断变化。
  • +
+
+

注意:NixOS不符合FHS标准!

+
+

三.分区大小

+

对各个分区进行容量分配时,需要根据系统的实际需求和用途来进行规划。一般而言在安装引导时可以选择让程序自动分区。

+
    +
  • 根目录(/):根目录是整个文件系统的起点,通常会分配较大的空间,以确保系统和应用程序有足够的空间运行。建议分配至少20GB的空间给根目录。
  • +
  • /home目录:/home目录用于存放用户的个人文件和数据,因此需要根据用户数量和存储需求来进行容量分配。一般情况下,建议为每个用户分配至少10GB的空间。
  • +
  • /var目录:/var目录用于存放系统运行时产生的可变数据,如日志文件、邮件、缓存文件等。根据系统的运行情况和日志文件的大小来进行容量分配,一般建议分配10-20GB的空间。
  • +
  • /tmp目录:/tmp目录用于存放临时文件和临时数据,通常不需要分配太大的空间。建议分配至少1-2GB的空间给/tmp目录。
  • +
  • /boot目录:/boot目录存放着启动Linux系统所需的引导文件,通常只需要分配几百MB的空间即可。
  • +
  • Swap分区:Swap分区是一种虚拟内存,用于暂时存放不常用的内存数据。当系统内存不足时,Linux会将一部分内存数据移动到Swap分区中,以避免内存耗尽导致系统崩溃。Swap分区的大小通常与系统内存大小有关,一般建议为系统内存的1.5-2倍。例如,如果系统内存为4GB,则建议设置Swap分区大小为6-8GB。
  • +
+
+

这里特别讲讲Swap分区

+
+

Swap分区可以通过以下几种方式实现:

+
    +
  • 交换分区(Swap Partition):创建一个独立的交换分区,通常是一个专门的分区,用于存放Swap数据。
  • +
  • 交换文件(Swap File):创建一个专门的文件用于存放Swap数据,而不是创建独立的分区。这种方式更加灵活,可以根据需要动态调整Swap的大小。
  • +
  • Swap大小:Swap的大小应该根据系统的内存大小和使用情况来确定,一般建议为系统内存的1.5-2倍。
  • +
  • Swap分区/文件的位置:Swap分区/文件应该位于较快的存储介质上,以确保交换操作的效率。 +Swap的优先级:如果同时存在多个Swap分区/文件,可以通过设置优先级来指定系统使用的Swap空间。
  • +
+

四.将 home 目录下的文件夹改为英文

+

可以使用 xdg-user-dirs-update 工具来更新用户目录为英文版本。你可以按照以下步骤进行:

+
    +
  1. +

    编辑用户目录配置文件: +打开或创建 ~/.config/user-dirs.dirs 文件,用文本编辑器编辑它:

    +
    nano ~/.config/user-dirs.dirs
    +
    +
  2. +
  3. +

    将目录名称更改为英文: +在该文件中,你可以看到类似以下的条目:

    +
    XDG_DESKTOP_DIR="$HOME/桌面"
    +XDG_DOWNLOAD_DIR="$HOME/下载"
    +XDG_DOCUMENTS_DIR="$HOME/文档"
    +XDG_MUSIC_DIR="$HOME/音乐"
    +XDG_PICTURES_DIR="$HOME/图片"
    +XDG_VIDEOS_DIR="$HOME/视频"
    +
    +

    将这些路径改为英文,例如:

    +
    XDG_DESKTOP_DIR="$HOME/Desktop"
    +XDG_DOWNLOAD_DIR="$HOME/Downloads"
    +XDG_DOCUMENTS_DIR="$HOME/Documents"
    +XDG_MUSIC_DIR="$HOME/Music"
    +XDG_PICTURES_DIR="$HOME/Pictures"
    +XDG_VIDEOS_DIR="$HOME/Videos"
    +
    +
  4. +
  5. +

    重命名现有的文件夹: +手动将 home 目录下的文件夹重命名为英文版本:

    +
    mv ~/桌面 ~/Desktop
    +mv ~/下载 ~/Downloads
    +mv ~/文档 ~/Documents
    +mv ~/音乐 ~/Music
    +mv ~/图片 ~/Pictures
    +mv ~/视频 ~/Videos
    +
    +
  6. +
  7. +

    应用更改: +完成以上操作后,运行以下命令应用新配置:

    +
    xdg-user-dirs-update
    +
    +
  8. +
+

这样,home 目录下的文件夹就会改为英文,并且系统也会正确识别这些新的目录路径。

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/learn-linux-for-pc-3/index.html b/public/learn-linux-for-pc-3/index.html new file mode 100644 index 0000000..eab0b43 --- /dev/null +++ b/public/learn-linux-for-pc-3/index.html @@ -0,0 +1,358 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

Linux之旅(三):内核/shell/包管理/文件系统/桌面环境

+ + + + + + +
+

前言 在Linux世界中,内核/shell/包管理/文件系统构成了Linux系统的核心,它们相互配合,共同构建了一个强大而稳定的操作环境。本文将深入探讨这些关键组成部分,解释它们的作用和原理,帮助读者更好地理解Linux系统的运作机制。

+

一.Linux内核

+

有许多不同的版本,每个版本都包含了一系列的功能改进、bug修复和性能优化。在Linux发行版中,通常会使用某个特定版本的Linux内核,或者在需要时进行升级。以下是一些常见的Linux内核及其主要特点:

+

Zen内核

+
    +
  • Zen内核是Linux内核的一个变体,旨在提供更好的性能和响应性。它通常包含了一些特定的调度程序和调优参数,以提高系统的负载均衡和响应速度。Zen内核也可能包含一些来自其他内核变体的功能和补丁,以进一步优化性能。
  • +
+

LTS内核

+
    +
  • LTS(Long-Term Support)内核是一种长期支持的内核版本,它会获得更长时间的更新和维护。LTS内核通常会选择一些相对稳定和经过充分测试的功能,并对其进行长期支持,以确保系统的稳定性和安全性。
  • +
+

Real-Time内核

+
    +
  • Real-Time内核是一种专门针对实时应用场景进行优化的内核变体。它通常包含了一些实时调度算法和机制,以确保系统能够及时响应各种事件,并满足实时性要求。Real-Time内核适用于一些对实时性要求较高的应用,如工业控制、机器人控制等领域。
  • +
+

Hardened内核

+
    +
  • Hardened内核是一种针对安全性进行优化的内核变体。它通常包含了一些安全增强功能和补丁,以提高系统的安全性和抵御攻击的能力。Hardened内核适用于一些对安全性要求较高的应用,如服务器、云计算等场景。
  • +
+

XanMod内核

+
    +
  • XanMod内核是一个基于Linux内核的自定义内核,旨在提供更好的响应性和性能。它包含了一些针对桌面和工作站系统优化的功能和补丁,如MuQSS调度器、BFQ I/O调度器等,以提高系统的响应速度和性能稳定性。XanMod内核还支持一些实时性应用,如音视频处理等,适用于对系统响应速度要求较高的用户。
  • +
+

CachyOS内核

+
    +
  • CachyOS内核是一个专门针对缓存优化的Linux内核变体。它包含了一些针对缓存系统优化的功能和调整,以提高系统的缓存性能和数据访问速度。CachyOS内核通常适用于需要高性能缓存的应用场景,如数据库服务器、Web服务器等。
  • +
+

这些内核变体针对不同的需求和使用场景进行了优化,可以根据具体的应用需求来选择合适的内核版本。例如,如果您需要更好的性能和响应性,可以选择Zen内核;如果您需要长期支持和稳定性,可以选择LTS内核;如果您需要实时性能,可以选择Real-Time内核;如果您需要更高的安全性,可以选择Hardened内核。

+

二.Linux Shell

+

在Linux系统中,有许多不同的Shell(命令行解释器),每种Shell都有自己的特点和用途。以下是一些常见的Linux Shell及其主要特点:

+

Bash(Bourne Again Shell)

+
    +
  • Bash是Linux系统中最常用的Shell之一,也是默认的命令行解释器。它是Bourne Shell的增强版,提供了丰富的功能和扩展性,包括命令历史、命令补全、作业控制等。Bash具有良好的兼容性和易用性,适用于日常的系统管理和脚本编程。
  • +
+

Zsh(Z Shell)

+
    +
  • Zsh是一种功能强大的Shell,提供了丰富的功能和扩展性,如更强大的命令补全、自动纠正拼写错误、主题和插件系统等。Zsh具有良好的可定制性和用户体验,适用于高级用户和程序员。
  • +
+

Fish(Friendly Interactive Shell)

+
    +
  • Fish是一种用户友好的交互式Shell,提供了直观的命令提示和自动补全功能,以及丰富的语法高亮和命令提示信息。Fish具有良好的用户体验和易用性,适用于初学者和普通用户。
  • +
+

Dash(Debian Almquist Shell)

+
    +
  • Dash是一种轻量级的Shell,专门设计用于系统启动过程和脚本执行。Dash具有较高的执行速度和较低的内存占用,适用于系统启动脚本和简单的脚本编程。
  • +
+

Bash是最常用的Shell之一,具有良好的兼容性和功能性;Zsh提供了更多的高级特性和定制选项,适用于高级用户和程序员;Fish具有友好的交互式体验和直观的用户界面,适用于初学者和普通用户;Dash则是一个轻量级的Shell,专门用于系统启动过程和简单的脚本编程。用户可以根据自己的需求和偏好选择合适的Shell。

+

三.Linux包管理器

+

在Linux系统中,有几种常见的包管理器,它们各自管理着不同的发行版,具有不同的特点和用途。以下是一些常见的Linux包管理器及其主要特点:

+

APT(Advanced Package Tool)

+
    +
  • APT是Debian系(如Debian、Ubuntu)中最常用的包管理器之一。它使用基于命令行的工具,如apt-getapt-cache等来安装、升级和删除软件包。APT还支持依赖关系的自动解决,使得软件包的安装和管理变得更加方便。
  • +
+

YUM(Yellowdog Updater, Modified)

+
    +
  • YUM是Red Hat系(如CentOS、Fedora)中常用的包管理器之一。它使用基于命令行的工具,如yum来管理软件包。YUM具有良好的依赖关系解决能力和事务处理功能,使得系统升级和软件包管理变得更加简单和可靠。
  • +
+

DNF(Dandified YUM)

+
    +
  • DNF是YUM的下一代版本,逐渐取代了YUM在Fedora和RHEL系列中的地位。DNF具有更快的包查询和事务处理能力,以及更友好的用户界面。它是未来主流的包管理器之一。
  • +
+

Pacman(Package Manager)

+
    +
  • Pacman是Arch Linux中常用的包管理器,也被一些其他发行版如Manjaro采用。Pacman使用简洁的命令,如pacman -S安装软件包、pacman -Syu更新系统等来管理软件包。Pacman具有简单、直观的界面和快速的操作速度,适用于对系统有一定了解的用户。
  • +
+

zypper

+
    +
  • zypper是openSUSE中常用的包管理器,它使用基于命令行的工具,如zypper installzypper update等来管理软件包。zypper具有良好的依赖关系解决能力和事务处理功能,使得系统升级和软件包管理变得更加简单和可靠。
  • +
+

dpkg

+
    +
  • dpkg是Debian系(如Debian、Ubuntu)中的低级别软件包管理工具,用于直接管理软件包的安装、升级和删除。它提供了一系列的命令,如dpkg -i安装软件包、dpkg -r删除软件包等。
  • +
+

RPM(RPM Package Manager)

+
    +
  • RPM是Red Hat系(如CentOS、Fedora)中的低级别软件包管理工具,用于直接管理软件包的安装、升级和删除。它提供了一系列的命令,如rpm -i安装软件包、rpm -e删除软件包等。
  • +
+

Portage

+
    +
  • Portage是Gentoo Linux中的包管理器,它使用源代码进行软件包的安装和管理。Portage具有高度定制化和灵活性,允许用户根据需要自定义软件包的编译参数和依赖关系。
  • +
+

Snap

+
    +
  • Snap是一种跨发行版的软件包格式和包管理器,允许用户在不同的Linux发行版上安装和管理软件包。Snap具有自包含性和隔离性,使得软件包的安装和升级变得更加简单和安全。
  • +
+

Flatpak

+
    +
  • Flatpak是另一种跨发行版的软件包格式和包管理器,类似于Snap,允许用户在不同的Linux发行版上安装和管理软件包。Flatpak提供了一种统一的应用分发和运行环境,使得软件包的安装和升级更加简单和可靠。
  • +
+

四.Linux文件系统

+

Linux系统支持多种文件系统,每种文件系统都有自己的特点和优势,适用于不同的应用场景和需求。以下是一些常见的Linux文件系统及其主要特点:

+

ext4

+
    +
  • ext4是Linux系统中最常用的文件系统之一,它是ext文件系统的后续版本,提供了更好的性能和扩展性。ext4支持更大的文件和分区大小,更快的文件系统检查和恢复速度,以及更高的性能和稳定性。
  • +
+

Btrfs

+
    +
  • Btrfs是一种先进的文件系统,具有许多先进的功能和特性,如快照、数据校验、数据压缩等。Btrfs支持在线扩展和收缩分区大小,以及动态添加和删除磁盘,适用于需要高级特性和灵活性的应用场景。此外,Btrfs对快照功能支持较好。
  • +
+
+

快照功能是一种文件系统的特性,它允许用户在特定时间点对文件系统的状态进行快照或备份,并且可以在需要时一键恢复到该时间点的状态。 +快照允许用户轻松地创建文件系统的历史版本,并在需要时回滚到特定的版本;快照允许用户在文件系统中进行实验和测试,并在测试失败或不需要时轻松地回滚到初始状态,以避免对系统造成影响。在升级或安装过程中出现问题时快速恢复到原始状态

+
+

XFS

+
    +
  • XFS是一种高性能的日志文件系统,适用于大型文件和高吞吐量的应用场景。XFS支持大容量的文件和分区,具有较低的碎片化和较高的并发性能,适用于大规模存储和数据分析等应用。
  • +
+

ZFS

+
    +
  • ZFS是一种先进的文件系统,具有强大的数据管理和保护功能,如快照、数据校验、数据压缩等。ZFS支持软件RAID和存储池(pool),以及动态添加和删除磁盘,适用于数据中心和大规模存储等应用场景。
  • +
+

F2FS

+
    +
  • F2FS是一种针对闪存存储设备进行优化的文件系统,具有高性能和高可靠性。F2FS支持闪存特性如块擦除计数(block erase count)和块生命周期管理(block lifetime management),适用于固态硬盘(SSD)和闪存卡等闪存设备。
  • +
+

五.Linux桌面环境

+

Linux系统有多种不同的桌面环境,每种环境都有其独特的特点、风格和用户体验。以下是一些常见的Linux桌面环境及其主要特点:

+

GNOME

+
    +
  • GNOME是一个功能强大、现代化的桌面环境,具有直观的用户界面和丰富的功能。它采用了扁平化的设计风格和简洁的用户界面,提供了丰富的应用程序和插件,适用于普通用户和开发人员。
  • +
+

KDE Plasma

+
    +
  • KDE Plasma是一个灵活、可定制的桌面环境,提供了丰富的特性和选项,如桌面特效、窗口管理器、小部件等。它采用了现代化的设计风格和强大的桌面管理功能,适用于高级用户和技术爱好者。
  • +
+

XFCE

+
    +
  • XFCE是一个轻量级、快速的桌面环境,具有简洁的用户界面和低资源消耗。它采用了传统的桌面布局和简约的设计风格,提供了基本的桌面管理功能和应用程序,适用于老旧计算机和资源有限的环境。
  • +
+

LXQt

+
    +
  • LXQt是一个轻量级、快速的桌面环境,是LXDE和Razor-qt的合并项目。它采用了现代化的设计风格和简洁的用户界面,提供了丰富的特性和可定制选项,适用于资源有限的环境和嵌入式系统。
  • +
+

Cinnamon

+
    +
  • Cinnamon是一个基于GNOME的桌面环境,具有类似于传统Windows桌面的用户界面和功能。它采用了传统的桌面布局和直观的用户体验,提供了丰富的特性和可定制选项,适用于对传统桌面风格有需求的用户。
  • +
+

GNOME和KDE Plasma提供了丰富的特性和高度定制化选项,适用于高级用户和开发人员;XFCE和LXQt则提供了轻量级和快速的用户体验,适用于资源有限的环境;Cinnamon则提供了类似于传统Windows桌面的用户界面和功能,适用于对传统桌面风格有需求的用户。可以根据自己的需求和偏好选择合适的桌面环境。

+
+

当然,也可以使用轻量级的窗口管理器。 +窗口管理器是Linux系统中控制窗口布局、管理窗口行为的关键组件。它们决定了窗口的外观和行为方式,以及如何管理和排列窗口。以下是一些常见的窗口管理器及其主要特点:

+
+

X Window Manager (XWM)

+
    +
  • X Window Manager是最基本的窗口管理器,用于管理X Window系统中的窗口。它提供了最基本的窗口布局和管理功能,如窗口移动、调整大小、最小化等。XWM本身并不提供任何外观效果,但可以与其他工具配合使用来实现更丰富的窗口管理和外观特性。
  • +
+

Openbox

+
    +
  • Openbox是一个轻量级的窗口管理器,具有简洁的用户界面和低资源消耗。它提供了丰富的自定义选项和扩展功能,如虚拟桌面、窗口装饰、键盘快捷键等。Openbox适用于资源有限的环境和对简洁风格有需求的用户。
  • +
+

i3

+
    +
  • i3是一个动态平铺窗口管理器,采用了平铺式布局,将窗口按照一定规则自动排列在屏幕上。它提供了快速的窗口切换和管理功能,支持键盘操作和自动布局调整,适用于需要高效多任务处理的用户。
  • +
+

Awesome

+
    +
  • Awesome是一个高度可定制的动态平铺窗口管理器,具有丰富的特性和扩展功能。它采用Lua脚本语言进行配置和定制,支持强大的自定义选项和扩展功能,适用于高级用户和技术爱好者。
  • +
+

KWin

+
    +
  • KWin是KDE桌面环境中的默认窗口管理器,具有丰富的特性和功能。它提供了多种窗口布局和管理选项,支持虚拟桌面、窗口效果、窗口组织等功能,适用于需要丰富特性和高度定制化的用户。
  • +
+

这些窗口管理器之间的主要异同在于窗口布局、外观效果、自定义选项和功能特性等方面。Openbox和i3提供了简洁的用户界面和低资源消耗,适用于资源有限的环境;Awesome和KWin则提供了丰富的特性和扩展功能,适用于高级用户和技术爱好者。用户可以根据自己的需求和偏好选择合适的窗口管理器。

+
+

Wayland和X11 +Wayland和X11都是用于Linux系统的图形显示协议,它们负责管理图形用户界面(GUI)的显示和交互。下面是它们的简要介绍以及异同点:

+
+
    +
  • +

    X11(X Window System): +X11是一个由MIT开发的图形显示协议,长期以来一直是Linux系统中最常用的图形显示系统。它采用客户端-服务器模型,图形应用程序(客户端)通过X服务器与显示设备(服务器)进行通信。X11提供了丰富的图形特性和功能,如窗口管理、窗口装饰、多任务处理等。

    +
  • +
  • +

    Wayland: +Wayland是一个由Red Hat主导开发的新一代图形显示协议,旨在取代X11成为Linux系统的标准图形显示系统。Wayland采用了现代化的设计理念和架构,取消了X11中复杂的客户端-服务器模型,将图形显示功能直接集成到操作系统中。Wayland具有更低的延迟和更高的性能,支持更好的硬件加速和多触摸设备,以及更简洁的代码结构。

    +
  • +
+

异同点

+
    +
  • 架构差异:X11采用了客户端-服务器模型,图形应用程序通过X服务器与显示设备进行通信;而Wayland取消了这种模型,将图形显示功能直接集成到操作系统中,减少了中间层的复杂性。
  • +
  • 性能差异:Wayland具有更低的延迟和更高的性能,支持更好的硬件加速和多触摸设备,使得图形显示更加流畅和响应。
  • +
  • 功能差异:X11提供了丰富的图形特性和功能,如窗口管理、窗口装饰、多任务处理等;Wayland在功能上相对较少,但提供了更简洁的代码结构和更好的性能。
  • +
  • 兼容性差异:X11在Linux系统中被广泛使用,拥有大量的应用程序和工具的支持;而Wayland在兼容性方面仍在发展中,尚未完全取代X11成为Linux系统的标准图形显示系统。
  • +
+

总的来说,Wayland是未来Linux系统中的趋势,具有更好的性能和更简洁的架构,但在兼容性和功能丰富度上仍有待改进。X11则是当前仍然广泛使用的图形显示系统,拥有丰富的生态和大量的应用程序支持。

+

六.后记

+

个人使用推荐Zen+Zsh+Pacman+Btrfs+Hyprland,并使用 paru xxx 来搜索软件包,使用paru -S xxx 安装软件。

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/learn-linux-for-pc-4/index.html b/public/learn-linux-for-pc-4/index.html new file mode 100644 index 0000000..b37748d --- /dev/null +++ b/public/learn-linux-for-pc-4/index.html @@ -0,0 +1,191 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

Linux之旅(四):Terminal,Console and Shell

+ + + + + + +
+

前言 在linux的学习过程中,我们常常遇到诸如 Terminal,Console,bash,zsh,shell,tty 等概念,这些概念常常被混淆,似乎都和命令行相关。本文从历史角度出发介绍它们的前世今生。

+

终端和控制台

+

终端,英文叫做 terminal ,通常简称为 term;控制台,英文叫做 console。

+

要明白这两者的关系,还得从最初的计算机说起。当时的计算机价格昂贵,一台计算机一般是由多个人同时使用的。在这种情况下一台计算机需要连接上许多套键盘和显示器来供多个人使用。在以前专门有这种可以连上一台电脑的设备,只有显示器和键盘,还有简单的处理电路,本身不具有处理计算机信息的能力,他是负责连接到一台正常的计算机上(通常是通过串口) ,然后登陆计算机,并对该计算机进行操作。当然,那时候的计算机操作系统都是多任务多用户的操作系统。这样一台只有显示器和键盘能够通过串口连接到计算机的设备就叫做终端。

+

而控制台又是什么回事呢?其概念来自于管风琴的控制台。顾名思义,控制台就是一个直接控制设备的台面(一个面板,上面有很多控制按钮)。 在计算机里,把那套直接连接在电脑上的键盘和显示器就叫做控制台。

+

终端是通过串口连接上的,不是计算机本身就有的设备,而控制台是计算机本身就有的设备,一个计算机只有一个控制台。计算机启动的时候,所有的信息都会显示到控制台上,而不会显示到终端上。也就是说,控制台是计算机的基本设备,而终端是附加设备。 当然,由于控制台也有终端一样的功能,控制台有时候也被模糊的统称为终端。

+

以上是控制台和终端的历史遗留区别。现在由于计算机硬件越来越便宜,终端和控制台的概念也慢慢演化了。终端和控制台由硬件的概念,演化成了软件的概念。 +  

+

内核与外壳

+

内核( Kernel )和外壳( Shell )是 linux 的两个主要部分。Kernel 是操作系统的核心,系统的文件管理、进程管理、内存管理、设备管理这些功能,都是由 Kernel 提供的。

+

用户和操作系统内核交流需要一个工具,那么这个工具就是 Shell。

+

什么是 Shell?在 Linux 中,最常见的 Shell 形式有命令行界面命令行界面和图形界面两种。并不是打开的那个终端窗口就是 Shell,如Alacritty、Gnome-Terminal、xterm 、kitty等程序,它们不是 Shell,而它们里面运行的 Bash、Zsh、fish 等命令行解释器程序,才是 Shell。

+

那 Alacritty、Gnome-Terminal、xtermxterm 是什么?

+

它们是终端模拟器。

+

前面提到过,在远古时代,终端和控制台都是有实体的。控制台直接和计算机在一起,你可以通过控制台控制计算机。终端通过数据线和计算机连接,终端也提供一个键盘和一个屏幕,你可以通过键盘向计算机下达指令,然后通过屏幕观察输出。

+

但是现在的计算机组成和以前不一样了,一般一台电脑都是自带键盘和屏幕,很少再外接终端设备。

+

所以 Linux 提供了另外一个更高级的功能,那就是虚拟终端。那就是在一台电脑上,通过软件的模拟,好像有好几个终端连接在这台计算机上一样。

+

现在说的终端,比如 linux 中的虚拟终端,都是软件的概念。虚拟终端称之为 tty,tty 是电传打字机电传打字机 Teletypewriter 的缩写,在带显示屏的视频终端出现之前,tty是最流行的终端设备。每一个 tty 都有一个编号,在/dev目录下有相应的设备文件。其中/dev/tty1到/dev/tty7可以通过 Ctrl+Alt+F1 到 Ctrl+Alt+F7 进行切换,也可以通过 chvt 命令进行切换,就好比是以前多人公用的计算机中的六个终端设备,这就是为什么这个叫“虚拟终端”的原因。

+

时代变迁

+

随着时间的推移,我们看到了从硬件到软件的转变,以及从多用户共享到个人使用的转变。这种变迁不仅影响了终端和控制台的概念,也塑造了我们对计算机的理解和期待。

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/learn-linux-for-pc-5/index.html b/public/learn-linux-for-pc-5/index.html new file mode 100644 index 0000000..76ebfbb --- /dev/null +++ b/public/learn-linux-for-pc-5/index.html @@ -0,0 +1,287 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

Linux之旅(五):BIOS-UEFI-MBR-GPT-GRUB

+ + + + + + +
+

前言 在计算机领域,系统引导和磁盘分区是至关重要的。本文将介绍BIOS与UEFI,MBR与GPT,以及它们之间的异同点。此外,我们还会讨论与这些概念密切相关的引导加载程序——GRUB。

+

BIOS

+
+

BIOS(Basic Input Output System),直译成中文名称就是"基本输入输出系统"。它是一组固化到主板中一个ROM芯片上的程序,它可以从CMOS中读写系统设置的具体信息。此程序保存着计算机最重要的基本输入输出程序、开机后的自检程序和系统自启动程序。简单来说,BIOS只认识设备,不认识分区、不认识文件。

+
+

UEFI

+
+

UEFI(统一可扩展固件接口)是一个公开的规范,定义了操作系统和平台固件之间的软件接口。UEFI 是传统 PC BIOS 的继承者,是取代传统BIOS的,相比传统BIOS来说,它更易实现,容错和纠错特性也更强。 它将引导数据存储在 .efi 文件中,而不是固件中。你经常会在新款的主板中找到 UEFI 启动模式。UEFI 启动模式包含一个特殊的 EFI 分区,用于存储 .efi 文件并用于引导过程和引导加载程序。

+
+
+

UEFI使用GPT的分区引导方案,支持更大的硬盘。由于省去了BIOS自检的过程,所以启动速度更快。传统BIOS主要支持MBR引导,UEFI则是取代传统BIOS,它加入了对新硬件的支持,其中就有支持2TB以上硬盘。

+
+

MBR

+
+

全新硬盘在使用之前必须进行分区格式化,硬盘分区初始化的格式主要有两种,分别为MBR格式和GPT格式。MBR是传统的分区表类型,当一台电脑启动时,它会先启动主板上的BIOS系统,BIOS再从硬盘上读取MBR主引导记录,硬盘上的MBR运行后,就会启动操作系统,但最大的缺点则是不支持容量大于2T的硬盘。

+
+

GPT

+
+

而GPT是另一种更先进的磁盘系统分区方式,它的出现弥补了MBR这个缺点,最大支持18EB的硬盘,是基于UEFI使用的磁盘分区架构。目前所有Windows系统均支持MBR,而GPT只有64位系统才能支持。BIOS只支持MBR引导系统,而GPT仅可用UEFI引导系统。正因为这样,现在主板大多采用BIOS集成UEFI,或UEFI集成BIOS,以此达到同时兼容MBR和GPT引导系统的目的。

+
+

GRUB

+
+

GRUB(GRand unified bootloader),多操作系统启动程序。它允许用户可以在计算机内同时拥有多个操作系统,并在计算机启动时选择希望运行的操作系统。

+

GRUB可用于选择操作系统分区上的不同内核,也可用于向这些内核传递启动参数。它是一个多重操作系统启动管理器,用来引导不同系统,如Windows、Linux。Linux常见的引导程序包括LILO、GRUB、GRUB2。

+
+

Legacy

+
+

如果你遇到过刚制作的U盘启动盘无法启动,或者新买的固态硬盘做好系统后无法启动,那么大概率的问题就出现在BIOS的引导模式的选择上,是UEFI还是Legacy。legacy启动模式是指BIOS 固件用来初始化硬件设备的引导过程,Legacy启动模式包含一系列已安装的设备,这些设备在引导过程中计算机执行 POST (开机自检)测试时会被初始化。传统引导将检查所有连接设备的主引导记录 (MBR),通常位于磁盘的第一个扇区。
+当它在设备中找不到引导加载程序时,Legacy会切换到列表中的下一个设备并不断重复此过程,直到找到引导加载程序,否则返回错误。

+
+

表格

+

BIOS/UEFI

+ + + + + +
BIOSUEFI
用于初始化计算机硬件并引导操作系统在计算机启动时运行
具有较少功能和灵活性具有更多功能和灵活性
支持更大的硬盘容量、更快的启动速度、更好的安全性和更多的扩展性v
通常具有图形用户界面(GUI)
+

MBR/GPT

+ + + + + +
MBRGPT
用于分区磁盘并存储分区布局信息用于分区磁盘并存储分区布局信息
支持最多4个主分区或3个主分区加1个扩展分区支持最多4个主分区或3个主分区加1个扩展分区支持最多4个主分区或3个主分区加1个扩展分区
具有更好的数据完整性和可靠性,使用校验和检测数据损坏
UEFI需要GPT格式的磁盘才能引导
+

UEFI/Legacy

+ + + + + + + + +
UEFI 引导模式Legacy引导模式
UEFI 提供了更好的用户界面Legacy引导模式是传统的且非常基本的
使用 GPT 分区方案使用 MBR 分区方案
UEFI 提供更快的启动时间相比UEFI,它的速度较慢
由于 UEFI 使用 GPT 分区方案,因此它可以支持多达 9 zB 的存储设备Legacy使用的 MBR 分区方案仅支持最多 2 TB 存储设备
UEFI 以 32 位和 64 位运行,支持鼠标和触摸板Legacy在仅支持键盘,仅 16 位模式下运行
它允许安全启动,防止加载未经授权的应用程序它还可能阻碍双启动,因为它将操作系统(OS)视为应用程序它不提供允许加载未经授权的应用程序的安全启动方法,未限制双启动
它具有更简单的更新过程与UEFI相比,它更复杂
+

组合

+
    +
  • +

    BIOS+MBR

    +

    这是最传统的,系统都会支持;唯一的缺点就是不支持容量大于2T的硬盘

    +
  • +
  • +

    BIOS+GPT

    +

    BIOS是可以使用GPT分区表的硬盘来作为数据盘的,但不能引导系统;若电脑同时带有容量小于2T的硬盘和容量大于2T的硬盘,小于2T的可以用MBR分区表安装系统,而大于2T的可以使用GPT分区表来存放资料。但系统须使用64位系统。

    +
  • +
  • +

    UEFI+MBR

    +

    可以把UEFI设置成Legacy模式(传统模式)让其支持传统MBR启动,效果同BIOS+MBR;也可以建立FAT分区,放置UEFI启动文件来,可应用在U盘和移动硬盘上实现双模式启动。

    +
  • +
  • +

    UEFI+GPT

    +

    如果要把大于2T的硬盘作为系统盘来安装系统的话,就必须UEFI+GPT。而且系统须使用64位系统,否则无法引导。但系统又不是传统在PE下安装后就能直接使用的,引导还得经过处理才行。

    +
  • +
+

系统的启动过程

+

从按下计算机的开机按钮到用户开始使用计算机,涉及了多个步骤和组件,让我们一起详细了解整个过程:

+

1. 电源启动

+
    +
  • 用户按下计算机的开机按钮,电源开始供电,计算机硬件开始初始化。电源将电流传递到主板上的BIOS/UEFI芯片。
  • +
+

2. BIOS/UEFI启动

+
    +
  • BIOS/UEFI芯片接收到电源信号后,开始执行初始化过程。它首先进行自检(POST),检测主板、CPU、内存等硬件设备的工作状态,并在显示屏上输出相关信息。
  • +
  • BIOS/UEFI根据配置的启动顺序(通常为硬盘、光盘、USB等)搜索启动设备,并加载位于启动设备上的引导加载程序。
  • +
+

3. 引导加载程序加载

+
    +
  • 引导加载程序(如GRUB)被加载到内存中,它负责后续的操作系统加载过程。GRUB通常会显示启动菜单,列出可用的操作系统选项。
  • +
  • 用户可以在GRUB菜单中选择要启动的操作系统,或者等待默认选项启动。
  • +
+

4. 操作系统加载

+
    +
  • 一旦选择了启动选项,引导加载程序会加载操作系统的内核和初始化RAM磁盘(initramfs/initrd)。
  • +
  • 内核加载完成后,操作系统开始启动初始化过程,包括加载系统服务、挂载文件系统、启动用户界面等。
  • +
+

5. 用户登录

+
    +
  • 操作系统初始化完成后,显示登录界面(如果配置了图形用户界面),用户输入用户名和密码登录系统。
  • +
  • 如果登录成功,操作系统加载用户的桌面环境或命令行界面,用户开始使用计算机。
  • +
+

各种引导加载程序

+ + + + + + + + + + +
特性GRUB(GRand Unified Bootloader)LILO(Linux Loader)systemd-boot(前身为 gummiboot)rEFInd(UEFI 引导管理器)
支持的系统类型BIOS 和 UEFI仅支持 BIOS 模式仅支持 UEFI仅支持 UEFI
多系统引导支持✅ 强大支持❌ 不支持多系统引导✅ 支持(需手动配置)✅ 自动检测操作系统
图形界面支持✅ 支持(可自定义主题)❌ 不支持❌ 不支持✅ 支持(可自定义主题)
配置方式配置文件(复杂)配置文件(简单)配置文件(简单)配置文件(简单)
命令行支持✅ 支持(交互式命令行)❌ 不支持❌ 不支持❌ 不支持
文件系统支持✅ 支持多种文件系统✅ 支持 ext2/ext3/ext4 等✅ 支持 ext4、FAT 等✅ 支持 ext4、FAT 等
安全启动支持✅ 支持(需配置)❌ 不支持✅ 支持(需配置)✅ 支持(需配置)
安装复杂度中等(需配置)较低较低中等(需配置)
适用场景多系统引导、复杂配置简单系统引导简单系统引导多系统引导、美观界面
+

后记

+ + +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/learn-linux-for-pc-6/index.html b/public/learn-linux-for-pc-6/index.html new file mode 100644 index 0000000..9a42f25 --- /dev/null +++ b/public/learn-linux-for-pc-6/index.html @@ -0,0 +1,353 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

Linux之旅(六):常用命令与性能分析

+ + + + + + +
+

前言 在学习Linux操作系统时,熟悉常用命令和性能分析工具是至关重要的。让我们一起探索Linux的世界,提升技能,解锁无限可能!

+ +
+

翻译自https://medium.com/netflix-techblog/linux-performance-analysis-in-60-000-milliseconds-accc10403c55。

+
+

问题背景

+

当登录到一台有性能问题的Linux服务器,第一分钟要检查什么?

+

在Netflix,我们拥有庞大的EC2 Linux虚拟机云,我们有众多性能分析工具来监视和诊断这些Linux服务器的性能。这些工具包括Atlas(负责整个虚拟机云的监控)和Vector(负责按需对虚拟机实例进行性能分析)。这些工具可以帮助我们解决大多数问题,但有时我们需要登录到虚拟机实例,并运行一些标准的Linux性能工具。

+

前60秒:摘要

+

在本文中,Netflix性能工程团队将使用您应该使用的标准Linux工具在命令行中向您展示一个性能诊断过程的前60秒。在60秒内,您可以通过运行以下十个命令来了解有关系统资源使用和运行进程的信息。最应该关注的是一些很容易理解的错误、饱和度指标和资源利用率等指标。饱和度是衡量资源负载超出其处理能力的指标,它可以通过观察请求队列的长度或等待时间反映出来。

+
uptime
+dmesg | tail
+vmstat 1
+mpstat -P ALL 1
+pidstat 1
+iostat -xz 1
+free -m
+sar -n DEV 1
+sar -n TCP,ETCP 1
+top
+
+

其中的一些命令需要安装sysstat软件包。这些命令暴露出的指标将帮助您完成一些USE方法:一种查找性能瓶颈的方法。它们涉及检查所有资源(CPU、内存、磁盘等)的利用率,饱和度和错误指标。在诊断过程中还应该注意检查和排除某些资源的问题。因为通过排除某些资源的问题,可以缩小诊断的范围,并指民后续的诊断。

+

uptime

+
$ uptime 
+23:51:26 up 21:31, 1 user, load average: 30.02, 26.43, 19.02
+
+

这是快速查看平均负载的方法,该平均负载指标了要运行的任务(进程)的数量。在Linux系统上,这些数字包括要在CPU上运行的进程以及在不中断IO(通常是磁盘IO)中阻塞的进程。这里给出了资源负载高层次的概览,但是没有其它工具就很难正确理解,值得快速看一眼。

+

这三个数字是指数衰减移动平均值,分别代表了1分钟、5分钟、15分钟的平均值。这三个数字使我们对负载如何随时间变化有了一定的了解。例如,如果您去诊断一个有问题的服务器,发现1分钟的值比15分钟的值低很多,那么您可能已经登录得太晚了,错过了问题。

+

在上面的例子中,平均负载有所增加,因为1分钟的值30相对15分钟的值19来说大了一些。数字变大意味着很多种可能:有可能是CPU的需求变多了,使用3和4中提到的vmstat或mpstat命令将可以进一步确认问题。

+

dmesg|tail

+
$ dmesg | tail
+[1880957.563150] perl invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0
+[...]
+[1880957.563400] Out of memory: Kill process 18694 (perl) score 246 or sacrifice child
+[1880957.563408] Killed process 18694 (perl) total-vm:1972392kB, anon-rss:1953348kB, file-rss:0kB
+[2320864.954447] TCP: Possible SYN flooding on port 7001. Dropping request.  Check SNMP counters.
+
+

该命令展示最近 10条系统消息。在这些系统消息中查找有可能引起性能问题的报错。上面的例子包括oom-killer和TCP丢弃了一个请求。

+

不能忘记这个步骤,dmesg通常对诊断问题很有价值。

+
## **vmstat 1**
+$ vmstat 1
+procs ---------memory---------- ---swap-- -----io---- -system-- ------cpu-----
+ r  b swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
+34  0    0 200889792  73708 591828    0    0     0     5    6   10 96  1  3  0  0
+32  0    0 200889920  73708 591860    0    0     0   592 13284 4282 98  1  1  0  0
+32  0    0 200890112  73708 591860    0    0     0     0 9501 2154 99  1  0  0  0
+32  0    0 200889568  73712 591856    0    0     0    48 11900 2459 99  0  0  0  0
+32  0    0 200890208  73712 591860    0    0     0     0 15898 4840 98  1  1  0  0
+
+

vmstat是虚拟内存统计(Virtual Memory Stat)的缩写,vmstat(8)是一个通常可用的工具(最初是在之前的BSD时代创建的),它每行打印一行服务器关键统计的概览。

+

vmstat使用参数1运行,意味着每1秒打印打印一次概览。命令输出的第一行展示的是从启动开始的平均值,而不是最近一秒的平均值。因此跳过第一行,除非您想学习并记住哪一列是哪一列。

+

要检查的列:

+

r:在CPU上运行并等待回合的进程数。由于它不包含IO,因此它比指示CPU饱和的平均负载提供了更多的信息。一个大于CPU核数的r值就是饱和的。 +free:空闲的内存(单位的KB)。如果计数很大,说明服务器有足够的内存,free -m命令将对空闲内存的状态有更好的说明。 +si、so:交换置入和交换置出。如果这两个值是非空,说明物理内存用完了,现在在使用交换内存了。 +us、sy、id、wa、st:这些是CPU时间的分类,其是所有CPU的平均值。它们是用户时间、系统时间(内核)、空闲时间、等待IO和被偷窃时间(被其它宾客系统进行使用,或宾客系统隔离的驱动程序域Xen) +通过将用户时间和系统时间这两个分类相加,即可判断CPU是否繁忙。一定的等待IO时间说明磁盘有可能是性能瓶颈。你可以认为等待IO时间是另一种形式的空闲时间,它提供了它是如何空闲的线索。

+

IO处理需要占用CPU系统时间。一个较高的CPU系统时间(超过20%)可能会很有趣,有必要进一步研究:也许内核在很低效地处理IO。

+

在上面的示例中,CPU时间基本全在用户时间,这说明应用程序本身在大量占用CPU时间。CPU的平均利用率也远远超过90%。这不一定是问题,可以使用r列来检查饱和度。

+

mpstat -P ALL 1

+
$ mpstat -P ALL 1
+Linux 3.13.0-49-generic (titanclusters-xxxxx)  07/14/2015  _x86_64_ (32 CPU)
+07:38:49 PM  CPU   %usr  %nice   %sys %iowait   %irq  %soft  %steal  %guest  %gnice  %idle
+07:38:50 PM  all  98.47   0.00   0.75    0.00   0.00   0.00    0.00    0.00    0.00   0.78
+07:38:50 PM    0  96.04   0.00   2.97    0.00   0.00   0.00    0.00    0.00    0.00   0.99
+07:38:50 PM    1  97.00   0.00   1.00    0.00   0.00   0.00    0.00    0.00    0.00   2.00
+07:38:50 PM    2  98.00   0.00   1.00    0.00   0.00   0.00    0.00    0.00    0.00   1.00
+07:38:50 PM    3  96.97   0.00   0.00    0.00   0.00   0.00    0.00    0.00    0.00   3.03
+[...]
+
+

此命令显示每个CPU的CPU时间明细,可用于检查不平衡的情况。单个热CPU说明是单线程应用程序在大量占用CPU时间。

+

pidstat 1

+
$ pidstat 1
+Linux 3.13.0-49-generic (titanclusters-xxxxx)  07/14/2015    _x86_64_    (32 CPU)
+07:41:02 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
+07:41:03 PM     0         9    0.00    0.94    0.00    0.94     1  rcuos/0
+07:41:03 PM     0      4214    5.66    5.66    0.00   11.32    15  mesos-slave
+07:41:03 PM     0      4354    0.94    0.94    0.00    1.89     8  java
+07:41:03 PM     0      6521 1596.23    1.89    0.00 1598.11    27  java
+07:41:03 PM     0      6564 1571.70    7.55    0.00 1579.25    28  java
+07:41:03 PM 60004     60154    0.94    4.72    0.00    5.66     9  pidstat
+07:41:03 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
+07:41:04 PM     0      4214    6.00    2.00    0.00    8.00    15  mesos-slave
+07:41:04 PM     0      6521 1590.00    1.00    0.00 1591.00    27  java
+07:41:04 PM     0      6564 1573.00   10.00    0.00 1583.00    28  java
+07:41:04 PM   108      6718    1.00    0.00    0.00    1.00     0  snmp-pass
+07:41:04 PM 60004     60154    1.00    4.00    0.00    5.00     9  pidstat
+
+

pidstat有点像top的每个进程摘要,但是会滚动打印,而不是清屏再打印。这对于观察一段时间内的模式以及将所看到的内容(复制&粘贴)记录到调查记录中很有用。

+

上面的示例显示两个Java进程要为消耗大量CPU负责。%CPU这一列是所有CPU核的总和,1591%说明Java进程差不多消耗了16个核的CPU。

+

iostat -xz 1

+
$ iostat -xz 1
+Linux 3.13.0-49-generic (titanclusters-xxxxx)  07/14/2015  _x86_64_ (32 CPU)
+avg-cpu:  %user   %nice %system %iowait  %steal   %idle
+          73.96    0.00    3.73    0.03    0.06   22.21
+Device:   rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
+xvda        0.00     0.23    0.21    0.18     4.52     2.08    34.37     0.00    9.98   13.80    5.42   2.44   0.09
+xvdb        0.01     0.00    1.02    8.94   127.97   598.53   145.79     0.00    0.43    1.78    0.28   0.25   0.25
+xvdc        0.01     0.00    1.02    8.86   127.79   595.94   146.50     0.00    0.45    1.82    0.30   0.27   0.26
+dm-0        0.00     0.00    0.69    2.32    10.47    31.69    28.01     0.01    3.23    0.71    3.98   0.13   0.04
+dm-1        0.00     0.00    0.00    0.94     0.01     3.78     8.00     0.33  345.84    0.04  346.81   0.01   0.00
+dm-2        0.00     0.00    0.09    0.07     1.35     0.36    22.50     0.00    2.55    0.23    5.62   1.78   0.03
+[...]
+
+

这是了解块设备(磁盘),应用的工作负载和产生的性能影响的绝佳工具。重点关注下面的指标:

+
    +
  • r/s、w/s、 rkB/s、 wkB/s:这些是设备每秒交付的读取、写入、读取千字节和写入千字节。使用这些来表征块设备的工作负载。性能问题可能是由于向块设备施加了过多的工作负载。
  • +
  • await:IO的平均时间,以毫秒为单位。这是应用程序所感受到的时间,它包括IO排队时间和IO服务时间。大于预期的平均时间可能表示块设备饱和或设备出现问题了。
  • +
  • avgqu-sz:发给设备的平均请求数。值大于1可以表明已达到饱和状态(尽管设备通常可以并行处理请求,尤其是在多个后端磁盘所组成的前端虚拟设备的情况下)。
  • +
  • %util:设备利用率。这是一个表征繁忙度的百分比,它表示设备每秒工作的时间。尽管它的值取决于设备,但值大于60%通常会导致性能不佳(也会通过await的值观察到)。接近100%的值通常表示饱和。
  • +
+

如果存储设备是有许多后端磁盘组成的前端逻辑磁盘设备,则100%的利用率可能仅意味着100%的时间正在处理某些IO,但是后端磁盘可能远远没有饱和,并且可能还可以处理更多的工作。

+

请记住,性能不佳的磁盘IO不一定是应用问题,通常可以使用许多技术以执行异步IO,以便使应用程序不会被阻塞住而产生直接产生IO延迟(例如,预读和缓冲写入技术)

+

free -m

+
$ free -m
+             total       used       free     shared    buffers     cached
+Mem:        245998      24545     221453         83         59        541
+-/+ buffers/cache:      23944     222053
+Swap:            0          0          0
+
+

右边两列:

+

buffers:缓冲区高速缓存,用于块设备I / O +cached:页面缓存,由文件系统使用 +我们只需要检查下它们的大小是否接近零。如果接近零的话,这可能导致较高的磁盘IO(可以使用iostat进行确认)和较差的性能。上面的示例看起来不错,每列都有较大的数据。

+

-/+ buffers/cache为已用和空闲内存提供较少让人产生混乱的值。Linux将可用内存用于高速缓存,但是如果应用程序需要,它们可以快速被回收。因此应以某种方式将缓存的内存包括在free列中,这也就是这一行的所做的。甚至还有一个网站专门讨论了这种混乱。

+

如果在Linux上使用ZFS,就像我们对某些服务所做的那么,因为ZFS具有自己的文件系统缓存,它们并不会反映在free -m的列中,因此这种场景下这种混乱还将存在。所以会看到似乎系统的可用内存不足,而实际上可根据需要从ZFS缓存中申请到内存。

+

sar -n DEV 1

+
$ sar -n DEV 1
+Linux 3.13.0-49-generic (titanclusters-xxxxx)  07/14/2015     _x86_64_    (32 CPU)
+12:16:48 AM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
+12:16:49 AM      eth0  18763.00   5032.00  20686.42    478.30      0.00      0.00      0.00      0.00
+12:16:49 AM        lo     14.00     14.00      1.36      1.36      0.00      0.00      0.00      0.00
+12:16:49 AM   docker0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
+12:16:49 AM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
+12:16:50 AM      eth0  19763.00   5101.00  21999.10    482.56      0.00      0.00      0.00      0.00
+12:16:50 AM        lo     20.00     20.00      3.25      3.25      0.00      0.00      0.00      0.00
+12:16:50 AM   docker0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
+
+

此工具可以检查网络接口的吞吐量:rxkB/s和txkB/s,作为工作负载的度量,还可以检查是否已达到网络接口的限制。在上面的示例中,eth0接收速率达到22MB/s,即176Mbit/s(远低于1Gbit/s的网络接口限制,假设是千兆网卡)。

+

此版本还具有%ifutil用来指示设备利用率(全双工双向),这也是我们使用的Brendan的nicstat工具测量出来的。就像nicstat一样,这个指标很难计算正确,而且在本例中好像不起作用(数据是0.00)。

+

sar -n TCP,ETCP 1

+
$ sar -n TCP,ETCP 1
+Linux 3.13.0-49-generic (titanclusters-xxxxx)  07/14/2015    _x86_64_    (32 CPU)
+12:17:19 AM  active/s passive/s    iseg/s    oseg/s
+12:17:20 AM      1.00      0.00  10233.00  18846.00
+12:17:19 AM  atmptf/s  estres/s retrans/s isegerr/s   orsts/s
+12:17:20 AM      0.00      0.00      0.00      0.00      0.00
+12:17:20 AM  active/s passive/s    iseg/s    oseg/s
+12:17:21 AM      1.00      0.00   8359.00   6039.00
+12:17:20 AM  atmptf/s  estres/s retrans/s isegerr/s   orsts/s
+12:17:21 AM      0.00      0.00      0.00      0.00      0.00
+
+

这是一些关键的TCP指标的摘要,包括:

+
    +
  • active / s:每秒本地启动的TCP连接数(例如,通过connect())。
  • +
  • passive/s:每秒远程启动的TCP连接数(例如,通过accept())。
  • +
  • retrans / s:每秒TCP重传的次数。 +主动和被动计数通常作为服务器TCP负载的粗略度量:新接受的连接数(被动)和新出站的连接数(主动)。将主动视为出站,将被动视为入站可能对理解这两个指标有些帮助,但这并不是严格意义上的(例如,考虑从localhost到localhost的连接)。
  • +
+

重新传输是网络或服务器问题的迹象;它可能是不可靠的网络(例如,公共Internet),也可能是由于服务器过载并丢弃了数据包。上面的示例仅显示每秒一个新的TCP连接。

+

top

+

$ top

+
top - 00:15:40 up 21:56,  1 user,  load average: 31.09, 29.87, 29.92
+Tasks: 871 total,   1 running, 868 sleeping,   0 stopped,   2 zombie
+%Cpu(s): 96.8 us,  0.4 sy,  0.0 ni,  2.7 id,  0.1 wa,  0.0 hi,  0.0 si,  0.0 st
+KiB Mem:  25190241+total, 24921688 used, 22698073+free,    60448 buffers
+KiB Swap:        0 total,        0 used,        0 free.   554208 cached Mem
+   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
+ 20248 root      20   0  0.227t 0.012t  18748 S  3090  5.2  29812:58 java
+  4213 root      20   0 2722544  64640  44232 S  23.5  0.0 233:35.37 mesos-slave
+ 66128 titancl+  20   0   24344   2332   1172 R   1.0  0.0   0:00.07 top
+  5235 root      20   0 38.227g 547004  49996 S   0.7  0.2   2:02.74 java
+  4299 root      20   0 20.015g 2.682g  16836 S   0.3  1.1  33:14.42 java
+     1 root      20   0   33620   2920   1496 S   0.0  0.0   0:03.82 init
+     2 root      20   0       0      0      0 S   0.0  0.0   0:00.02 kthreadd
+     3 root      20   0       0      0      0 S   0.0  0.0   0:05.35 ksoftirqd/0
+     5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H
+     6 root      20   0       0      0      0 S   0.0  0.0   0:06.94 kworker/u256:0
+     8 root      20   0       0      0      0 S   0.0  0.0   2:38.05 rcu_sched
+
+

top命令包括我们之前检查的许多指标。运行它可以很方便地查看是否有任何东西与以前的命令有很大不同,这表明负载是可变的。

+

top命令不太好的地方是,随着时间的推移很难看到指标变化的模式,这在提供滚动输出的vmstat和pidstat之类的工具中可能更清楚一点。如果您没有足够快地暂停输出(Ctrl-S暂停,Ctrl-Q继续),在屏幕输出被top命令清除后,间歇性问题的证据也可能被丢失了。

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/learn-linux-for-pc-7/index.html b/public/learn-linux-for-pc-7/index.html new file mode 100644 index 0000000..9df2c47 --- /dev/null +++ b/public/learn-linux-for-pc-7/index.html @@ -0,0 +1,202 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

Linux之旅(七):系统与终端字体设置

+ + + + + + +
+

前言 一个好看的字体会提高工作效率与审美.Linux 下的字体可以很漂亮,但需要一些设置.

+ +

随着 FreeType2 由于专利过期默认开启了高质量的 LCD 优化,以及一批高质量的开源字体的公布,Linux 上的中文字体渲染比过去好了太多.

+
+

Windows 的字体渲染从技术上来说是相当先进的,问题是在中文字体的选择上实在是一坨...

+
+

选择字体

+

近几年来出现了一大批自由字体(包括工作量极大的 CJK 字体),使 Linux 下的字体选择一下子丰富了起来.如果愿意花一点时间的话,可以去ArchWiki 上看看,里面涵盖了相当多的自由字体.

+

终端字体

+

Maple Mono,这是一款字形整洁、拥有手写风格的斜体、细粒度配置、内置 Nerd-Font、中英文2:1等宽 的字体.我使用的:

+
MapleMono-Bold
+
+

阅读器字体

+

霞鹜文楷,一款开源中文字体,基于 FONTWORKS 出品字体 Klee One 衍生.我使用的:

+
LXGW WenKai
+
+

浏览器字体

+
拉丁字体
+├── Inter -无衬线,类似于 Roboto 但更适合屏幕显示的字体 
+├── Noto Serif -衬线
+└── Sarasa Term SC -等宽,拉丁文字符严格为半宽的字体,中英文混排时较协调
+├── 如果不适应这种较瘦的字体风格, 则可以尝试使用:
+│   ├── Adobe Source Pro
+│   ├── Cascadia Code
+│   └── Fira Code
+中文字体
+├── Noto Sans CJK SC (思源黑体)
+└── Noto Serif CJK SC(思源宋体)
+
+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/links/index.html b/public/links/index.html new file mode 100644 index 0000000..abeb129 --- /dev/null +++ b/public/links/index.html @@ -0,0 +1,242 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+
+ +

Yon Zilch

+ + + + + +
+

blog.yon.im/

+ +
+ +
+ +
+ +

diredocks

+ + + + + +
+

blog.clickfling.top

+ +
+ +
+ +
+ +

Ice Year の位面

+ + + + + +
+

blog.iceyear.eu.org

+ +
+ +
+ +
+ +

Purkit's Blog

+ + + + + +
+

www.fovir.fyi

+ +
+ +
+ +
+ +

Milvoid

+ + + + + +
+

milvoid.com/

+ +
+ +
+ +
+ +

世纪大道 | 春风少年兄

+ + + + + +
+

blog.0pt.icu

+ +
+ +
+ +
+ +
+ + + + +
+ + + diff --git a/public/links/link-1/index.html b/public/links/link-1/index.html new file mode 100644 index 0000000..29a8a7e --- /dev/null +++ b/public/links/link-1/index.html @@ -0,0 +1,158 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

Yon Zilch

+ + + + +
+

blog.yon.im/

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/links/link-2/index.html b/public/links/link-2/index.html new file mode 100644 index 0000000..0c0994c --- /dev/null +++ b/public/links/link-2/index.html @@ -0,0 +1,165 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

diredocks

+ + + + +
+

blog.clickfling.top

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/links/link-3/index.html b/public/links/link-3/index.html new file mode 100644 index 0000000..df502d8 --- /dev/null +++ b/public/links/link-3/index.html @@ -0,0 +1,165 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

Ice Year の位面

+ + + + +
+

blog.iceyear.eu.org

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/links/link-4/index.html b/public/links/link-4/index.html new file mode 100644 index 0000000..92e84b9 --- /dev/null +++ b/public/links/link-4/index.html @@ -0,0 +1,165 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

Purkit's Blog

+ + + + +
+

www.fovir.fyi

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/links/link-5/index.html b/public/links/link-5/index.html new file mode 100644 index 0000000..42beb40 --- /dev/null +++ b/public/links/link-5/index.html @@ -0,0 +1,165 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

Milvoid

+ + + + +
+

milvoid.com/

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/links/link-6/index.html b/public/links/link-6/index.html new file mode 100644 index 0000000..df6fdb0 --- /dev/null +++ b/public/links/link-6/index.html @@ -0,0 +1,158 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +

世纪大道 | 春风少年兄

+ + + + +
+

blog.0pt.icu

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/logo.css b/public/logo.css new file mode 100644 index 0000000..b5150a4 --- /dev/null +++ b/public/logo.css @@ -0,0 +1 @@ +.logo{display:flex;align-items:center;text-decoration:none;background:var(--accent);color:#000;padding:5px 10px} \ No newline at end of file diff --git a/public/main.css b/public/main.css new file mode 100644 index 0000000..8c6731b --- /dev/null +++ b/public/main.css @@ -0,0 +1 @@ +html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit}body{margin:0;padding:0;font-family:Hack,DejaVu Sans Mono,Monaco,Consolas,Ubuntu Mono,monospace;font-size:1rem;line-height:1.54;background-color:var(--background);color:var(--color);text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-webkit-overflow-scrolling:touch;-webkit-text-size-adjust:100%}@media (max-width: 683px){body{font-size:1rem}}h1,h2,h3,h4,h5,h6{display:flex;align-items:center;font-weight:bold;line-height:1.3}h1{font-size:1.4rem}h2{font-size:1.3rem}h3{font-size:1.2rem}h4,h5,h6{font-size:1.15rem}a{color:inherit}img{display:block;max-width:100%}img.left{margin-right:auto}img.center{margin-left:auto;margin-right:auto}img.right{margin-left:auto}p{margin-bottom:20px}figure{display:table;max-width:100%;margin:25px 0}figure.left,figure img{margin-right:auto}figure.center,figure img{margin-left:auto;margin-right:auto}figure.right,figure img{margin-left:auto}figure figcaption{font-size:14px;padding:5px 10px;margin-top:5px;background:var(--accent);color:var(--background)}figure figcaption.left{text-align:left}figure figcaption.center{text-align:center}figure figcaption.right{text-align:right}code{font-family:Hack,DejaVu Sans Mono,Monaco,Consolas,Ubuntu Mono,monospace;font-feature-settings:normal;background:var(--accent-alpha-20);padding:1px 6px;margin:0 2px;font-size:.95rem}pre{font-family:Hack,DejaVu Sans Mono,Monaco,Consolas,Ubuntu Mono,monospace;padding:20px;font-size:.95rem;overflow:auto;border-top:1px solid rgba(255,255,255,.1);border-bottom:1px solid rgba(255,255,255,.1)}@media (max-width: 683px){pre{white-space:pre-wrap;word-wrap:break-word}}pre code{padding:0;margin:0;background:none}blockquote{border-top:1px solid var(--accent);border-bottom:1px solid var(--accent);margin:40px 0;padding:25px}@media (max-width: 683px){blockquote{padding-right:0}}blockquote:before{content:"”";font-family:Georgia,serif;font-size:3.875rem;position:absolute;left:-40px;top:-20px}blockquote p:first-of-type{margin-top:0}blockquote p:last-of-type{margin-bottom:0}blockquote p{position:relative}blockquote p:before{content:">";display:block;position:absolute;left:-25px;color:var(--accent)}table{table-layout:fixed;border-collapse:collapse;width:100%;margin:40px 0}table,th,td{border:1px dashed var(--accent);padding:10px}th{color:var(--accent)}ul,ol{margin-left:30px;padding:0}ul li,ol li{position:relative}@media (max-width: 683px){ul,ol{margin-left:20px}}ol ol{list-style-type:lower-alpha}.container{display:flex;flex-direction:column;padding:40px;max-width:864px;min-height:100vh;margin:0 auto}@media (max-width: 683px){.container{padding:20px}}.content{display:flex}hr{width:100%;border:none;background:var(--border-color);height:1px}.hidden{display:none} \ No newline at end of file diff --git a/public/network-cdn/index.html b/public/network-cdn/index.html new file mode 100644 index 0000000..2179c9d --- /dev/null +++ b/public/network-cdn/index.html @@ -0,0 +1,395 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

Network的艺术:CDN技术与应用

+ + + + + + +
+

前言 内容分发网络(CDN)是一组分布在不同地理位置的服务器网络,使用户能够就近获取内容,从而降低延迟并缓解源站压力​.

+

什么是CDN?

+

内容分发网络(CDN)是一组分布在不同地理位置的服务器网络,旨在将网站或应用的静态资源(如HTML、图片、视频等)缓存到距离用户更近的节点,以缩短传输路径、降低带宽成本并提高访问速度​.CDN通过“缓存”机制,在全球多个数据中心临时存储内容副本,用户发起请求时无需回源到主服务器,就能从最近的缓存节点获取数据,从而显著改善页面加载时间和整体用户体验​.相比传统的单点源站访问,CDN在用户和源站之间增加了分层缓存,通过负载均衡技术和智能路由,将访问请求定向到最优节点,既减轻了源站压力,又提升了网络抗拥塞能力和可用性​.

+

在现代互联网中,内容分发网络(CDN)和域名系统(DNS)相互配合,共同提升了网页和多媒体内容的访问速度与可靠性.CDN通过在全球分布的缓存节点上存储静态资源,使用户能够就近获取内容,从而降低延迟并缓解源站压力​.而DNS则负责将用户的域名请求导向适当的CDN节点,通过CNAME重定向、全局负载均衡(GSLB)、Anycast及EDNS扩展等技术,实现智能化的流量调度和最优路径选择​.

+

CDN的核心功能与优势

+
    +
  • +

    加速访问:将内容存储于距离用户更近的节点,减少传输延迟,常见于视频点播、大文件下载等场景​.

    +
  • +
  • +

    减轻源站压力:缓存请求可直接由CDN节点响应,降低源站带宽和计算资源消耗,有助于应对突发流量和DDoS攻击​.

    +
  • +
  • +

    高可用与弹性扩展:全球分布的节点架构,使内容分发具备冗余能力,单点故障不会影响整体服务,且可动态扩容以应对业务增长.

    +
  • +
+

CDN与DNS的结合方式

+
    +
  1. 通过CNAME实现权威DNS指向CDN
  2. +
+

当用户在浏览器中输入域名发起请求时,首先触发本地DNS解析过程;如果该域名已开通CDN服务,其DNS解析记录通常配置为一条CNAME(别名)记录,指向CDN运营商提供的专用域名;本地DNS服务器再将解析权交给CDN的权威DNS服务器,从而实现对CDN网络的接入​.

+

CDN的权威DNS服务器根据用户请求的域名,返回一个“全局负载均衡设备”的IP地址,该IP并非最终缓存节点,而是GSLB层用于智能调度的入口地址;浏览器接收到该IP后,向GSLB层发起实际内容请求​.

+
    +
  1. 全局负载均衡(GSLB)与智能DNS
  2. +
+

GSLB(Global Server Load Balancing)是CDN架构中最核心的部分,负责根据多种因素(用户IP地理位置、节点健康状态、节点负载情况等)动态选择最优区域负载均衡节点或缓存服务器,向用户提供最低延迟和最佳性能的服务​.

+

这一过程通常也基于DNS解析完成:当GSLB层接到DNS查询请求时,智能DNS服务器会返回针对该用户最优的缓存节点IP,从而实现“DNS级”的流量调度和负载均衡​.

+
    +
  1. Anycast与EDNS扩展
  2. +
+

Anycast路由:部分CDN运营商在全球部署相同IP的多个节点,利用BGP Anycast技术使得用户请求自动路由到网络拓扑上“最近”的节点,增强访问的网络路径效率与容灾能力​.

+

EDNS Client Subnet(EDNS-CS):传统DNS仅看到发起查询的递归DNS服务器IP,难以准确判断终端用户位置;EDNS-CS协议在DNS请求中携带部分客户端IP前缀,使权威DNS能更细粒度地进行地理定位与节点选取,大幅提升了基于DNS的智能调度精度​.

+

为什么加了CDN之后网站的自签名证书也被信任了?

+
+

在启用 CDN 后,终端用户看到的并不是您在源站(origin)上配置的自签名证书,而是 CDN 边缘节点(edge)所出示的、由受信任 CA 签发的“边缘证书”.也就是说,浏览器与 CDN 边缘之间的 TLS 握手完全独立于您源站和自签名证书的存在,源站的自签名证书仅用于 CDN 与源站之间的“后端”加密连接,不会暴露给最终用户浏览器​.

+
+

CDN 模式下的 TLS 终止

+
    +
  • +

    DNS/CNAME 指向 +当您为域名启用 CDN 后,通常会在 DNS 中将该域名的 CNAME 记录指向 CDN 运营商提供的专用域名,本地递归 DNS 随后会将解析权交给 CDN 供应商的权威 DNS,实现请求切入 CDN 网络​.

    +
  • +
  • +

    边缘节点出示证书 +用户发起 HTTPS 请求时,浏览器直接与就近的 CDN 边缘节点建立 TLS 连接,边缘节点会出示由受信任 CA(如 Let's Encrypt、DigiCert 等)签发的“边缘证书”,而非您源站的自签名证书​.

    +
  • +
  • +

    源站连接加密 +在边缘节点接收并缓存用户流量后,CDN 再以 HTTPS(或 HTTP,根据配置)向源站发起请求.此时,您可以在源站使用自签名证书(或 Cloudflare Origin CA 自签名证书),仅保证 CDN 与源站之间的加密传输,且该证书对终端用户浏览器不可见​.

    +
  • +
+

SSL/TLS 加密模式对自签名证书的影响

+

以 Cloudflare 为例,常见的四种 SSL/TLS 模式对自签名证书的处理策略如下:

+
    +
  • +

    Flexible:浏览器 ↔ CDN 边缘 使用 HTTPS;CDN 边缘 ↔ 源站 使用 HTTP,不接触证书验证.

    +
  • +
  • +

    Full:浏览器 ↔ CDN 边缘 使用 HTTPS;CDN 边缘 ↔ 源站 使用 HTTPS,但不验证源站证书的 CA 链和域名匹配,可使用自签名证书​. +Cloudflare Docs

    +
  • +
  • +

    Full (strict):浏览器 ↔ CDN 边缘 使用 HTTPS;CDN 边缘 ↔ 源站 使用 HTTPS,严格验证源站证书是否由受信任 CA 签发且域名匹配,不支持自签名证书​. +Cloudflare Docs

    +
  • +
  • +

    Off:关闭 HTTPS,加密支持完全关闭.

    +
  • +
+

若您选择 Full 或 Flexible 模式,即使源站使用自签名证书,CDN 也不会在边缘层对其进行验证,仍会正常转发和缓存内容;而用户浏览器只会看到 CDN 边缘提供的受信任证书,因此不会出现“不受信任”警告​.

+
+

为什么浏览器会信任? 浏览器内置了受信任的根证书列表,CDN 边缘出示的证书链会完整地链接到某个系统信任根,而您的自签名证书则不在此列表内,因而只有源站连接可被 CDN 信任,而非终端浏览器​.CDN 则作为“可信中间人”,它信任自签名证书以加密与源站的通信,而浏览器仅信任 CDN 边缘的 CA 签发证书,二者互不干扰,有效隔离了自签名的风险.

+
+

如何开启Full (Strict)模式?

+

​要在 Cloudflare 上启用 Full (Strict) 模式,以确保 CDN 与源站之间的通信既加密又验证证书的有效性,请按照以下步骤操作:​

+

✅ 步骤 1:确保源站配置了有效的 SSL/TLS 证书

+

在启用 Full (Strict) 模式之前,您的源站必须安装一个有效且受信任的 SSL/TLS 证书.​您可以选择以下方式之一:​

+
使用公共 CA 颁发的证书:如 Let's Encrypt、DigiCert、GlobalSign 等.
+
+使用 Cloudflare Origin CA 证书:这是 Cloudflare 提供的免费证书,专为与其边缘节点通信设计.​
+
+

确保证书未过期,且域名匹配正确.如果使用 Cloudflare Origin CA 证书,请在源站服务器上正确安装,并配置服务器(如 Nginx、Apache)以使用该证书.​

+

✅ 步骤 2:在 Cloudflare 仪表板中启用 Full (Strict) 模式

+
登录到您的 Cloudflare 仪表板.
+
+选择您要配置的站点.
+
+在左侧菜单中,点击 “SSL/TLS”.
+
+在 “概览(Overview)” 标签下,找到 “SSL/TLS 加密模式(SSL/TLS encryption mode)”.
+
+选择 “Full (Strict)” 模式.​
+
+

更改后,Cloudflare 会立即应用此设置.​建议等待几分钟,然后通过浏览器访问您的网站,确保一切正常运行.​

+

🔗 注意事项

+

如果源站使用的是自签名证书或过期的证书,启用 Full (Strict) 模式后,Cloudflare 将无法建立连接,用户可能会看到 526 错误.

+

确保源站服务器的时间设置正确,以避免因时间不一致导致的证书验证失败.

+

DNSSEC是什么?

+

DNSSEC(Domain Name System Security Extensions,域名系统安全扩展)是一组为 DNS 协议设计的安全机制,旨在通过数字签名验证 DNS 数据的真实性和完整性,防止域名解析过程中的数据篡改和伪造.

+
    +
  1. DNSSEC 的工作原理
  2. +
+

DNSSEC 通过引入以下关键机制来增强 DNS 的安全性:​

+
    +
  • +

    数字签名(RRSIG 记录):​每个 DNS 记录集(如 A、MX、CNAME 等)都会生成一个对应的数字签名,确保记录在传输过程中未被篡改.​

    +
  • +
  • +

    公钥发布(DNSKEY 记录):​用于存储验证数字签名所需的公钥.​这些公钥本身也通过上级域的签名进行验证,形成信任链.​

    +
  • +
  • +

    委派签名者(DS 记录):上级域使用 DS 记录存储下级域的 DNSKEY 记录的摘要,确保公钥的真实性.

    +
  • +
  • +

    不存在性证明(NSEC/NSEC3 记录):用于明确指示某个 DNS 记录不存在,防止攻击者伪造不存在的记录.

    +
  • +
+

通过这些机制,DNSSEC 建立了一条从根域开始的信任链,逐级验证每个域的 DNS 数据,确保其未被篡改且来源可信.

+
    +
  1. DNSSEC 的局限性
  2. +
+
    +
  • +

    不加密数据内容:DNSSEC 仅对 DNS 数据进行签名验证,并不加密查询和响应内容,因此无法防止数据被监听.

    +
  • +
  • +

    部署复杂性:​实施 DNSSEC 需要域名注册商、DNS 服务提供商和客户端解析器的共同支持,部署和维护相对复杂.​

    +
  • +
  • +

    性能影响:​由于引入了额外的签名验证过程,DNSSEC 可能会增加 DNS 查询的响应时间和系统资源消耗.​

    +
  • +
+
    +
  1. DNSSEC 的优势
  2. +
+
    +
  • +

    防止 DNS 欺骗和缓存投毒:​通过验证 DNS 数据的真实性,DNSSEC 能有效防止攻击者伪造 DNS 响应,将用户引导至恶意网站.​

    +
  • +
  • +

    增强互联网基础设施安全性:​作为互联网信任体系的一部分,DNSSEC 为其他安全协议(如 DANE)提供基础支持.​

    +
  • +
+

CDN的位置选择

+

Netlify在考虑到CDN成本以及可用性的情况下选择了以下这些地区以保证全球大部分访客访问他们的服务都能有不错的连接性和访问速度。

+
欧洲中部(德国法兰克福)
+南美(巴西圣保罗)
+美东(美国弗吉尼亚)
+美西(美国旧金山)
+亚洲(新加坡)
+大洋洲(澳大利亚悉尼)
+
+

那么Netlify为什么会选择把CDN节点放到这些地区呢?

+

1.弗吉尼亚,美东的弗吉尼亚被誉为“全球数据中心之都",美国政府对这个地区的网络投入非常大,使得弗吉尼亚的全球互联(美国本土、欧洲以及到南美洲)优秀。

+

2.旧金山,面向亚太和美西的访客。需要注意的是美西对亚太的网络连接比较优秀,但是到南美不太理想,甚至还有丢包的情况。

+

3.法兰克福,面向欧洲用户,德国法兰克福或者荷兰阿姆斯特丹都是不错的选择。

+

4.新加坡,亚太地区数据中心的枢纽,到印度、日本、越南、香港、中国移动的联通性都不错。

+

5.悉尼,土澳出了名的国际互联不太好,悉尼节点主要是服务本地和周边。

+

6.圣保罗,南美市场。

+

常见CDN的IP列表

+
+

需要注意的是有些CDN的回源IP并不用作节点IP,比如Cloudflare的回源IP仅作回源IP使用,如果要获取Cloudflare的节点IP,可前往https://bgp.tools/as/13335#prefixes。而有些CDN的回源IP同时被用作CDN节点,比如BunnyCDN和Gcore CDN。

+
+

Cloudflare

+
# https://www.cloudflare.com/ips-v4
+103.21.244.0/22
+103.22.200.0/22
+103.31.4.0/22
+104.16.0.0/13
+104.24.0.0/14
+108.162.192.0/18
+131.0.72.0/22
+141.101.64.0/18
+162.158.0.0/15
+172.64.0.0/13
+173.245.48.0/20
+188.114.96.0/20
+190.93.240.0/20
+197.234.240.0/22
+198.41.128.0/17
+
+# https://www.cloudflare.com/ips-v6
+2400:cb00::/32
+2405:8100::/32
+2405:b500::/32
+2606:4700::/32
+2803:f800::/32
+2a06:98c0::/29
+2c0f:f248::/32
+
+

Gcore

+
https://api.gcore.com/cdn/public-ip-list
+
+

BunnyCDN

+
https://api.bunny.net/system/edgeserverlist
+https://api.bunny.net/system/edgeserverlist/plain
+
+

Cloudfront

+
https://d7uri8nf7uskq.cloudfront.net/tools/list-cloudfront-ips
+https://files.imunify360.com/static/whitelist/v2/cloudfront-cdn.txt
+
+

CDN77

+
https://files.imunify360.com/static/whitelist/v2/cdn77.txt
+
+

Fastly

+
https://api.fastly.com/public-ip-list
+
+

Keycdn

+
https://www.keycdn.com/shield-prefixes.json
+
+

quic.cloud

+
https://quic.cloud/ips
+
+

Google CDN

+
https://files.imunify360.com/static/whitelist/v2/google-cdn.txt
+
+

CacheFly

+
https://cachefly.cachefly.net/ips/cdn.txt
+
+

Akaima

+
https://techdocs.akamai.com/origin-ip-acl/docs/update-your-origin-server
+
+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/network-download-1/index.html b/public/network-download-1/index.html new file mode 100644 index 0000000..996bf1e --- /dev/null +++ b/public/network-download-1/index.html @@ -0,0 +1,473 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

Network的艺术:下载技术的历史

+ + + + + + +
+

前言 下载,就是将我们所需要的文件数据,通过网络从拥有该文件资源的计算机上传输过来并保存到我们的计算机上,供我们使用。本系列将详细讲述各种常见网络下载技术的原理,包括HTTP,FTP,BT等等。

+ +

下载技术的历史可以追溯到计算机网络的早期发展阶段。以下是下载技术的一些历史里程碑:

+
    +
  • +

    早期网络时代(1960s - 1980s): +在计算机网络的早期阶段,下载技术并不像今天这样普及。主要的网络是由军方和学术机构使用的封闭网络,例如阿帕网(ARPANET)。在这个时期,文件通常通过物理介质(如磁带、磁盘或纸带)传输,而不是通过网络进行下载。

    +
  • +
  • +

    BBS时代(1980s - 1990s): +随着电子通信的发展,出现了电子公告板系统(BBS)。BBS是一种允许用户通过拨号访问的系统,用户可以在BBS上发布和下载文件。下载文件的过程通常是通过模拟调制解调器将文件从BBS服务器下载到个人计算机上。

    +
  • +
  • +

    Internet时代的起步(1990s): +1990年代初,随着互联网的普及,出现了许多文件下载协议和工具。其中最知名的是FTP(文件传输协议),它允许用户通过网络下载文件到自己的计算机上。FTP是早期互联网上常用的文件传输方式之一,但它需要用户在计算机上安装专用的FTP客户端软件。

    +
  • +
  • +

    万维网时代的兴起(1990s): +随着万维网(World Wide Web)的诞生,HTTP(超文本传输协议)成为了互联网上最流行的协议之一。HTTP允许用户通过标准的Web浏览器直接从Web服务器上下载文件。这一时期也出现了许多下载管理器和加速器,例如IDM(Internet Download Manager),用于提高文件下载的速度和管理。

    +
  • +
  • +

    P2P文件共享时代(2000s至今): +P2P(点对点)文件共享技术允许用户直接从其他用户的计算机上下载文件,而不是从中央服务器下载。著名的P2P协议包括BitTorrent和eDonkey等。这些技术使得文件下载更加分布式,并且提供了更高的下载速度和可靠性。

    +
  • +
  • +

    流媒体下载和订阅服务(2000s至今): +随着互联网带宽的增加,视频和音频流媒体下载成为主流。诸如Netflix、Spotify和Apple Music等订阅服务提供了通过互联网访问大量内容的途径,用户可以通过流媒体服务下载并观看/收听内容,而无需等待完全下载。

    +
  • +
+

一.HTTP 下载

+

HTTP,全名 HyperText Transfer Protocol,超文本传输协议。 +HTTP协议是一种无状态的、应用层协议,用于传输超文本数据,如HTML、图片、音视频等。

+

HTTP下载的基本原理:

+
    +
  1. +

    浏览器请求:用户在浏览器中点击下载链接或按钮时,浏览器会向服务器发送HTTP请求,请求下载指定的文件。

    +
  2. +
  3. +

    服务器响应:服务器收到下载请求后,会根据请求中的信息找到对应的文件,并将文件内容打包成HTTP响应发送给客户端。

    +
  4. +
  5. +

    传输过程:一旦浏览器接收到服务器的响应,就开始从服务器下载文件。这个过程可以简单地分为以下几个步骤:

    +
      +
    • 建立连接:浏览器与服务器之间建立TCP连接。
    • +
    • 请求文件:浏览器发送一个GET请求,请求下载文件的内容。
    • +
    • 接收文件:服务器将文件以HTTP响应的形式发送给浏览器。
    • +
    • 下载文件:浏览器接收到文件数据,逐步将其存储到本地硬盘中的临时文件中。
    • +
    +
  6. +
  7. +

    下载完成:一旦文件的所有数据都被下载到本地,浏览器就会将临时文件转移到用户指定的下载文件夹中,完成文件的下载过程。

    +
  8. +
+

在整个HTTP下载过程中,浏览器会根据服务器返回的HTTP响应头中的一些信息来确定如何处理下载文件,例如文件类型、大小、以及是否支持断点续传等。此外,如果用户使用的是下载管理器或浏览器插件,这些工具还可以提供更多的下载管理功能,如多线程下载、下载加速、断点续传等。

+

当我们点击一个链接时,浏览器会检查链接指向的目标是什么类型。如果是浏览器支持的类型,比如一个 HTML 文件,也就是另一个网页,则会跳转到新页面。

+

如果是不能直接由浏览器打开的文件类型,比如一个 EXE 格式的软件包,这时就会调用浏览器的下载机制,开始下载。如果装有下载工具的浏览器插件,浏览器则会将下载任务转交给下载工具进行,等待一段时间,下载完成之后,这个文件就会出现在我们的下载文件夹中。这就是最基本的下载,HTTP 下载。

+

二.拨号上网

+

上世纪 90 年代,中国互联网的发展初期,在当时计算机上网只能通过电话线路,经由调制解调器来进行,因此称作拨号上网。

+

拨号上网的基本原理:

+
    +
  • +

    调制解调器(Modem):在拨号上网时,计算机通过调制解调器将数字数据转换成模拟信号发送到电话线路上,以及接收从电话线路传来的模拟信号并将其转换成数字数据。调制解调器是连接计算机和电话线路的关键设备。

    +
  • +
  • +

    拨号过程:用户在计算机上设置拨号连接,输入拨号号码(通常是ISP提供的拨号号码),计算机通过调制解调器拨号建立连接。拨号过程中,调制解调器会发送一系列信号给拨号接入点,以建立与网络服务提供商(ISP)的连接。

    +
  • +
  • +

    网络连接:一旦拨号成功,计算机与ISP的服务器建立起网络连接。在拨号过程中,计算机会获取到一个IP地址,这个IP地址是计算机在网络上的唯一标识符,用于进行数据传输。

    +
  • +
  • +

    数据传输:一旦网络连接建立,计算机就可以通过调制解调器在电话线路上发送和接收数据。数据传输可以是双向的,用户可以浏览网页、发送电子邮件、下载文件等。

    +
  • +
  • +

    电话和上网的冲突:在拨号上网的过程中,电话线路和上网信号不能同时传输,如果在上网过程中接听电话,网络连接会中断。这是因为电话和上网信号共用同一条电话线路,无法同时传输。

    +
  • +
  • +

    断线重连:如果网络连接因为电话中断或其他原因而中断,用户需要重新拨号连接到ISP的服务器,继续上网。这种中断和重连过程是拨号上网时常见的情况。

    +
  • +
+

拨号上网的速度较慢,且容易受到电话和上网信号冲突的影响,因此在宽带互联网普及后逐渐被淘汰。

+

当时的网费不是按年收取的,而是与打电话一样按时计费,费用大约为每小时 20 元,而且这还是房地产未爆发之时的 20 元。

+

当时最高网速为 56 kbps,也就是 7 KB/s,一首 MP3 音乐大约为 4 M,需要下载 10 分钟。但如果是一个红警 2 的游戏,约 200 M,那就需要下载 8 小时。8 小时的网费 160 元,而一张盗版光盘只需要 5 元。因此,虽然光盘现如今已经被沉入了历史长河,但它依然留存在老一代游戏玩家心中,是他们无法抹去的一份美好记忆。

+

下载时间长、网费贵,最要命的是电话信号和上网信号不能并行传输,接听来电会中断网络传输,然后你就必须重新下载。

+

三.断点续传

+

拨号上网的电话和网络不能同时进行的致命问题,在几年后随着 ADSL 宽带技术的出现,得以解决。但这并不是说,下载就不再会被中断了。电话是不怕了,但死机、停电、软件崩溃、服务器当机等等,还有无数种暂停下载的情况。

+

断点续传的基本原理:

+
    +
  • +

    HTTP Range和Content-Range头字段:为了支持断点续传,HTTP 1.1标准在1999年引入了Range和Content-Range头字段。这些字段允许客户端指定要请求的文件的特定范围,并且允许服务器指定响应的内容的范围。

    +
  • +
  • +

    客户端支持:下载工具需要能够识别并利用HTTP Range头字段。当下载中断时,下载工具会将已经下载的部分保存到本地硬盘上,同时记录下已下载的字节数和文件的URL等信息。

    +
  • +
  • +

    中断处理:如果下载过程中出现网络中断或其他原因导致下载中断,下载工具会保存当前已下载的部分,并在下次恢复下载时利用HTTP Range头字段向服务器发出请求,请求从中断处继续下载。

    +
  • +
  • +

    服务端支持:服务器需要能够处理带有Range头字段的请求,并能够正确响应所请求的文件的特定范围。服务器根据客户端请求的字节范围返回相应部分的文件内容,并且在响应头中包含Content-Range字段指示所返回的文件部分的范围和总大小。

    +
  • +
  • +

    续传合并:一旦下载工具完成对剩余部分的下载,它会将先前保存的部分和新下载的部分合并成完整的文件。这通常涉及到文件操作,如将两个文件的内容按顺序拼接到一起。

    +
  • +
+

然而,要实现断点续传,客户端和服务器双方都必须支持相关的HTTP头字段和逻辑,否则无法进行断点续传。

+

四.多线程下载

+

互联网早期,上网用户少,但内容提供商更少。因此提供下载的网站一般都是满带宽运行的。而且在晚上的高峰期,能分给每个用户的带宽就更少了。因此大多数用户的下载速度都很低,远低于自己的网络带宽,这对于按时计费的上网环境来说,就是一种极大的浪费。因此人们又希望能有一种可以提升下载速度的方法。

+

多线程下载Multi-threaded Download是一种通过同时启动多个下载线程来加快文件下载速度的技术。以下是多线程下载的基本原理:

+
    +
  • +

    并行下载:在开始下载任务时,下载工具会同时启动多个下载线程,每个线程负责下载文件的不同部分。例如,如果设定了5个下载线程,那么下载工具会将文件分成5个部分,每个线程负责下载其中的一部分。

    +
  • +
  • +

    断点续传:每个下载线程都利用断点续传技术,向服务器发出请求,并在HTTP请求中指定自己要下载的文件的起止位置。服务器根据这些请求返回相应的文件部分,而不是整个文件。

    +
  • +
  • +

    并行下载过程:各个下载线程同时下载文件的不同部分,因此可以充分利用网络带宽资源,加快文件的下载速度。由于每个线程独立工作,所以它们之间互不影响,即使某个线程下载中断,其他线程仍然可以继续下载。

    +
  • +
  • +

    文件合并:当所有下载线程都完成了各自部分的下载后,下载工具将这些部分按顺序合并成完整的文件。这通常是在本地文件系统中进行的简单文件操作,将各个部分的内容按顺序写入到一个文件中。

    +
  • +
  • +

    提升下载速度:多线程下载技术可以有效地提升文件的下载速度,尤其是对于大文件或者带宽较小的网络连接。通过利用多个下载线程同时下载文件的不同部分,可以充分利用网络带宽资源,加快文件的下载速度。

    +
  • +
+

多线程下载技术的出现极大地改善了用户在互联网上下载文件的体验,使得用户可以更快地获取所需的文件内容。许多下载工具如网络蚂蚁、FlashGet、IDM等都采用了多线程下载技术,为用户提供了更高效的下载服务。

+

五.FTP 下载

+

FTPFile Transfer Protocol即文件传输协议是一种用于在计算机之间传输文件的标准网络协议。它提供了一种简单而有效的方式,允许用户从一个主机(FTP服务器)下载文件到另一个主机(客户端)或上传文件到服务器。

+

以下是FTP协议及其下载原理的详细说明:

+

FTP协议基础

+
    +
  • +

    工作模式:FTP使用客户端-服务器模式,客户端向服务器发出命令并接收服务器的响应来进行文件传输。

    +
  • +
  • +

    端口:FTP使用TCP协议,服务器默认监听端口为21,用于控制连接,数据传输则使用动态端口(通常是20)。

    +
  • +
  • +

    认证:用户需要通过用户名和密码进行身份验证才能连接到FTP服务器。

    +
  • +
  • +

    命令和响应:FTP客户端通过发送命令到服务器来执行各种操作,例如列出目录、下载文件、上传文件等。服务器接收到命令后,执行相应的操作,并向客户端发送响应。

    +
  • +
+

FTP下载原理

+

FTP下载的基本原理涉及以下几个步骤:

+
    +
  • +

    建立连接:客户端向服务器发送连接请求,服务器响应并建立控制连接。控制连接用于发送FTP命令和接收服务器响应。

    +
  • +
  • +

    身份验证:客户端发送用户名和密码进行身份验证。一旦验证通过,客户端可以开始执行FTP命令。

    +
  • +
  • +

    浏览文件:客户端可以使用FTP命令浏览服务器上的文件和目录结构,例如LIST命令用于列出目录内容。

    +
  • +
  • +

    选择文件:客户端通过FTP命令选择要下载的文件,例如RETR命令用于从服务器下载文件。

    +
  • +
  • +

    建立数据连接:在下载文件之前,客户端需要与服务器建立数据连接。数据连接用于实际传输文件内容。

    +
  • +
  • +

    下载文件:一旦数据连接建立,服务器开始向客户端发送文件内容。客户端接收文件数据,并将其保存到本地文件系统中。

    +
  • +
  • +

    关闭连接:文件传输完成后,客户端关闭数据连接,并向服务器发送命令关闭控制连接。

    +
  • +
+

主动模式和被动模式

+

FTP连接可以使用主动模式(Active Mode)或被动模式(Passive Mode)进行数据传输。

+
    +
  • +

    主动模式:在主动模式下,客户端向服务器的数据端口(通常是端口20)发送连接请求,服务器通过控制端口(端口21)响应,并在数据端口上发送数据。

    +
  • +
  • +

    被动模式:在被动模式下,客户端发送连接请求到服务器的控制端口(端口21),服务器响应并在一个随机的高端口打开一个监听,并将这个端口号发送给客户端。然后客户端连接到服务器的高端口上进行数据传输。

    +
  • +
+

被动模式通常用于避免防火墙问题和NAT设备的限制,因为它允许数据连接从服务器向客户端发起,而不是从客户端向服务器发起。

+

安全性

+

FTP协议最初设计时并没有考虑到安全性,因此在传输过程中文件内容以明文形式传输,存在安全风险。为了解决这个问题,可以通过使用FTP over SSL(FTPS)或FTP over SSH(SFTP)等安全扩展来加密传输数据。

+

六.BT下载

+

BT 全称 BitTorrent,一般不翻译,非要翻译的话,那就是“比特洪流”。它一般指基于 P2P 下载机制而设计的一个具体协议。BT 三大客户端µTorrent、qBittorrent 和 Transmission,µ是希腊字母,不好输入,所以也常写作 uTorrent。

+

BT下载技术的基本原理:

+
    +
  • +

    种子文件创建:一个用户想要共享一个文件时,他会创建一个种子文件。种子是一个很小的,大约几十 kB 的,后缀名为 .torrent 的文件。种子内存储有该资源所包含文件的文件名、哈希值和 Tracker,哈希值是一个长度几十位不等的16进制数字,用于判断一个文件是否因传输过程而损坏或被恶意篡改。其原理可以简单理解为将一个超大数字的每位相加,再求余,这样以来,文件中哪怕有一个字节的变动或增减,都会导致对应哈希值的变化。BT 客户端在文件下载完成后会重新计算其哈希值,并与种子内保存的哈希值进行比较。如果不同,则表示下载过程中出现数据损坏,需要重新下载。BT 协议还会对体积较大的文件进行切片处理,从而减小重新下载所需的数据量。

    +
  • +
  • +

    分块:文件会被分成一个个固定大小的块(通常为256KB或512KB),每个块都有一个唯一的标识符。

    +
  • +
  • +

    连接Tracker服务器:用户启动BT客户端后,首先需要连接Tracker服务器来获取其他参与文件共享的用户信息。Tracker 是一个服务器地址,与 HTTP 下载服务器不同的是,它不保存文件内容,只保存文件的哈希值,和已下载过该文件的所有用户的 IP 地址。也就是说,当你获得一个种子文件,并添加到 BT 客户端之后,BT 客户端所做的第一步就是,向种子内保存的 Tracker 服务器询问“哪些人已经下载了这个文件?”Tracker 服务器就会将对应的 IP 地址列表,返回给你的 BT 客户端Tracker服务器会返回一份参与文件共享的用户列表,称为peer list。

    +
  • +
  • +

    连接Peers:P2P 英文全称 Peer To Peer。一般不翻译,非要翻译的话,那就是“点对点”或“对等”,即这种新型下载方式的运作机制。 +根据Tracker服务器返回的peer list,用户的BT客户端会尝试连接其中的其他用户(也称为peer)。通过这些连接,用户可以请求和发送文件块。

    +
  • +
  • +

    下载块:一旦连接到其他用户,用户的客户端就会开始请求文件的不同块。客户端会根据需要的块选择合适的peer,并向其发送请求。其他peer收到请求后,会响应并将相应的块发送给请求者。

    +
  • +
  • +

    上传块:用户的BT客户端不仅仅是下载文件,也在上传文件。当用户下载了一个块后,它也会成为一个可供其他用户下载的资源,用户的客户端会将这个块发送给其他请求者。

    +
  • +
  • +

    分块验证:一旦下载完成,客户端会验证每个块的完整性。如果发现某个块不完整或者损坏,客户端会请求相同的块,直到下载到一个完整的块。

    +
  • +
  • +

    做种:当一个用户完全下载了文件并且保持BT客户端运行时,他就成为了一个seeder(种子),即可供其他用户下载文件的资源。种子会周期性地向Tracker服务器发送自己的信息,以便其他用户找到他并下载文件。

    +
  • +
+
+

迅雷也会从别的 BT 软件那里下载资源,但它拒绝向其共享,它只共享给其他同样使用迅雷的用户。这严重违背 P2P 共享的公平原则,因此迅雷被称为吸血雷。

+
+
+

专用下载链接

+
+
    +
  • 最常见的专用下载链接就是迅雷链接 thunder://。其他少见的还有 QQ 旋风的 qqdl:// 和快车的 flashget://。 +这种链接的本质是“加密的 http 链接”,发明这种链接的目的是打击竞争对手,并同时给用户制造障碍,让用户不得不使用他们的产品。本来用浏览器就能直接下载的 http 链接,用户还非得先下载一个迅雷。 +而它们使用的加密手段极其拙劣,均使用 Base64 进行编码。因此网上有大量下载地址的转换工具,而 Base64 发明的目的是为了让二进制文件,得以用纯文本进行表达,以方便搭配 data URL 将小文件嵌入代码,或者让只支持纯文本,不支持二进制传输的地方得以实现二进制文件的传输。而被这三个家伙用于纯文本到纯文本的加密,一定会让 Base64 的发明者气个半死。
  • +
+

七.PT 下载

+

PTPrivate Tracker是一种私有的BitTorrent Tracker系统,与公开的BitTorrent网络不同,它需要用户进行注册和认证才能访问和下载文件。下面是PT下载技术的基本原理:

+
    +
  • +

    注册和认证:用户需要注册一个账户,并且经过认证才能够访问PT站点。认证通常包括通过邀请码注册或者通过一定的上传/下载比例限制。

    +
  • +
  • +

    获取种子文件:与公开的BitTorrent网络不同,PT站点上的种子文件通常需要用户登录后才能够访问和下载。种子文件包含了文件的元数据信息以及Tracker服务器的地址。

    +
  • +
  • +

    连接Tracker服务器:用户启动BT客户端后,首先需要连接PT站点的Tracker服务器来获取其他参与文件共享的用户信息。Tracker服务器会返回一份peer list。

    +
  • +
  • +

    连接Peers:与公开的BitTorrent网络类似,用户的BT客户端会根据Tracker服务器返回的peer list,尝试连接其他参与文件共享的用户(peer)。

    +
  • +
  • +

    下载块:一旦连接到其他用户,用户的客户端就会开始请求文件的不同块。客户端会根据需要的块选择合适的peer,并向其发送请求。其他peer收到请求后,会响应并将相应的块发送给请求者。

    +
  • +
  • +

    上传块:与公开的BitTorrent网络类似,用户的BT客户端在下载文件的同时也会上传文件。下载的块也会被上传给其他用户。

    +
  • +
  • +

    分块验证:下载完成后,客户端会验证每个块的完整性。如果发现某个块不完整或者损坏,客户端会请求相同的块,直到下载到一个完整的块。

    +
  • +
  • +

    保种:保种是PT站点非常重要的概念。用户需要保持下载的文件在客户端中并继续上传给其他用户,以维持站点的健康和分享比例。保种也是PT站点会设置上传/下载比例限制的原因之一。

    +
  • +
+

PT 与 BT 的一个较大的区别是,PT 会时刻计算每个用户的上传量和下载量,由此来得到每个用户的一个指标“分享率”,分享率过低会被取消使用资格。

+

因此与 BT 用户的想法“我要多多下载,然后下完就跑” 相比,PT 用户的想法则是“你们赶紧下载我的资源吧,我还有一季美剧要追呢”。最终结果就是,大多数 BT 种子都下载不动,而 PT 种子则都可以高速下载。

+

八.ed2k/电骡/VeryCD/

+

ed2k 全称 eDonkey2000 即“电驴”,同时也是其协议 ed2k:// 的名称,一般不翻译,非要翻译的话,那就是“电驴链接”。其与 BT 1.0 是同一时期出现,且为技术原理相同的软件。ed2k 与 BT 相比,它不需要种子文件所有必要信息,比如文件名、哈希值、Tracker 地址等信息都编码并保存在这个地址中。唯一的缺点是不能像种子一样保存多个文件,比如用一个种子文件保存整部电视剧的全部剧集或者更夸张的,一个种子保存一万部电影。

+

2002 年,一个 eDonkey2000 的程序员用户 ,对当时的 eDonkey2000 客户端不满意,并且相信自己能做出更好的 P2P 软件。因此着手开发,并于同年推出了首个版本,他们的软件名为 eMule,中文名“电骡”。电骡兼容电驴的 ed2k 网络,并在电驴的基础上增加了许多其他功能。电骡也基于 Kademlia 协议算法,开发了自己的的去中心化网络 “Kad 网络”。但最最重要的一点是,它是开源的,这一点为 ed2k 在国内的普及奠定了基础。

+

2003 年,国内的两个 P2P 下载爱好者,建立了一个 ed2k 资源分享网站 VeryCD。这个网站一直被认为是国内资源最丰富的网站,各种影视、音乐、游戏、软件等资源应有尽有。

+

2005 年,也就是 BT 2.0 元年,在美国唱片协会的状告之下,eDonkey2000关闭了网站,并停止了软件更新。在关闭前夕,其原作者根据 Kademlia 协议算法,开发出了电驴的去中心化 P2P 分享网络 “Overnet”,并更新到了 eDonkey2000 客户端的最后一个版本中。这样使得它的软件在网站关闭之后依然可以使用。

+

2007 年,在开源的 eMule 基础上,easyMule诞生了 。对于中文名,他们没有新起,而是尝试强行将自己称作“电驴”。可能是他们觉得电驴已经死了,由他们来继承,或者认为自己是电驴的一个支脉吧。正是这一点,让国内用户对四个英文名 eDonkey、eMule、easyMule、VeryCD 和中文名电驴之间傻傻分不清楚。

+

2012 年VeryCD被迫下架了其全部资源的 ed2k 下载链接,此后 VeryCD 也逐渐淡出了人们的视野。

+

九.磁力连接

+

磁力链是协议名为 magnet: 的下载链接。magnet 是“磁铁”的意思,它在原理和用法上与电驴链接 ed2k:// 几乎是一样的。它允许用户通过简单的URL链接来获取到资源的相关信息,而无需下载一个独立的种子文件。

+

基于Hash值的标识:磁力链接是通过资源内容的哈希值来唯一标识的。这个哈希值通常是使用SHA-1算法计算的,并且对应着特定资源的唯一标识符。

+

包含元数据信息:磁力链接中还包含了一些资源的元数据信息,如文件名、文件大小、文件分块信息等。这些信息通常是经过URL编码的,并以一种特定的格式嵌入到磁力链接中。

+

无需中心化Tracker:与传统的Torrent文件不同,磁力链接中并不包含Tracker服务器的地址。这意味着用户可以直接通过磁力链接获取到资源相关的peer列表,无需依赖中心化的Tracker服务器。

+

使用DHT网络:当用户使用磁力链接时,他们的BitTorrent客户端会通过DHT(分布式哈希表)网络来获取资源的相关信息。DHT网络是一个去中心化的网络,允许BitTorrent客户端在没有Tracker服务器的情况下发现其他拥有相同资源的peer。

+

动态获取信息:使用磁力链接下载资源时,用户的BitTorrent客户端会动态地从其他拥有相同资源的peer处获取到资源的元数据信息,如文件列表、文件大小等。这样,用户可以立即开始下载资源,而无需等待种子文件下载完成。

+

随着电驴和 VeryCD 的关闭,以后互联网上的各种资源的下载,会逐渐从 ed2k 全部转向 magnet。磁力链还可以与 BT 搭配使用,也就是为多个文件制作好 BT 种子之后,再为种子文件制作一个磁力链接,这样就可以既享受 BT 种子支持多个文件的优点,又可以享受 ed2k 和磁力链只需要链接,不需要文件的优点。

+

十.BT 2.0

+

BT 的文件虽然是分布式存储的,但它们的联络员 Tracker 依然是中心化的,只需要借助法律手段,端掉一个 Tracker 服务器,即可让所有 BT 下载瘫痪。因此为了实现完全的防封禁,必须实现完全的去中心化。

+

2002 年,美国纽约大学的两位学者,发表了他们的研究成果 Kademlia 协议,并且由 BT 发明者 BitTorrent 客户端,率先于 2005 年支持这种基于 Kademlia 协议的,不依赖Tracker 服务器的 BT 技术。随后,其他 BT 客户端也陆续跟进支持,这标志着 BT 进入 BT 2.0 的时代。

+

BT 2.0下载原理:

+
    +
  • +

    分布式Hash表:BT 2.0可能会引入分布式Hash表来替代传统的Tracker服务器。DHT 分布式哈希表网络,英文全称 Distributed Hash Table。其原理就是将原来由 Tracker 服务器保存的“文件哈希 - 文件存储位置” 的映射信息分散存储在 DHT 网络的各个节点中,并且留有冗余,即多份,以保证单个节点在关机之后,也不会影响文件的查询。分布式Hash表可以使peer更容易地发现彼此,减少了对中心化Tracker服务器的依赖。当用户想要下载文件时,他们可以通过Hash值查询分布式Hash表,获取与文件相关的peer列表。

    +
  • +
  • +

    加密和安全性:BT 2.0引入更强大的加密技术来保护数据传输的安全性和用户的隐私。包括对传输数据进行端到端的加密,以及对用户身份进行更严格的验证和认证。

    +
  • +
  • +

    内容验证和真实性:BT 2.0引入更多的内容验证机制,以确保下载的文件的真实性和完整性。包括数字签名、哈希验证和数据完整性检查等技术,以防止文件被篡改或损坏。

    +
  • +
  • +

    带宽管理和QoS优化:BT 2.0改进带宽管理算法,以优化数据传输的效率和性能。包括更智能的下载调度、流量控制和质量of服务(QoS)机制,以确保下载过程中的良好用户体验。

    +
  • +
  • +

    去中心化和匿名性:BT 2.0加强去中心化和匿名性方面的功能,以保护用户的隐私和匿名性。包括使用Tor网络、区块链技术和匿名代理等,以确保用户的下载行为不被追踪或监视。

    +
  • +
+

十一.网盘

+

网盘,即位于网络上的硬盘。云的概念兴起以后也被一些厂商称为“云盘”.

+

网盘的概念最早起源于电子邮箱的附件存储.相比本地磁盘有诸多优点,它可以防止重要资料因电脑故障而丢失,可以防止机密数据因电脑丢失而外泄。代替 U 盘和移动硬盘在家里和公司之间共享文件。如果你的网盘是同步盘的话,还免去了频繁的手动上传和下载.

+

虽然网盘的几T空间看起来很唬人,但对所有用户来说,填充这几 TB 空间的往往是视频资源,而且绝大多数用户均是视频的消费者,也就是从网上下载视频,而不是自己拍摄视频。因此这些视频资源都是高度重叠的。现实情况就是 1000 个用户使用的 1TB 空间,不是占用了 1000TB 的服务器空间,而是 10TB。

+

十二.离线下载

+

离线下载准确来说,离线下载其实就是其他人替你挂机下载,下载完成后,再传给你。

+

添加下载任务:用户通过离线下载服务提供的网页或应用程序界面,将需要下载的文件链接或种子链接添加到下载任务列表中。

+

解析链接:离线下载服务会对添加的下载链接进行解析,提取出其中的文件信息和下载地址。

+

远程下载:离线下载服务会以其自身的网络连接,从文件来源服务器下载文件。这个过程完全在服务端进行,用户的设备不直接参与下载过程。

+

存储文件:下载完成后,文件会被保存在离线下载服务的服务器上,而不是用户的本地设备上。用户可以在需要时通过网页或应用程序界面访问和管理这些文件。

+

提供下载链接:一旦文件下载完成,离线下载服务会生成一个新的下载链接或提供直接的文件下载链接给用户。用户可以使用这个链接来下载文件到自己的设备上。

+

刚开始使用离线下载的用户,可能会惊叹于离线下载的“秒完成”。这是因为已经有人先于你离线下载过这个资源了,这就是“资源重叠率”。

+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/network-how-email-works-1/index.html b/public/network-how-email-works-1/index.html new file mode 100644 index 0000000..45b2cfd --- /dev/null +++ b/public/network-how-email-works-1/index.html @@ -0,0 +1,264 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

电子邮件是如何工作的:SPF/DKIM/DMARC

+ + + + + + +
+

前言 在互联网的日常使用中,电子邮件作为一项基础服务扮演着重要的角色。尽管在过去几十年里出现了各种新型的通讯方式,但电子邮件仍然保持着其不可替代的地位。了解电子邮件的工作原理,有助于更好地理解这一基础服务是如何运作的。

+

一. 基于协议的传输

+

与许多其他基于协议的应用一样,电子邮件依赖于一系列协议来进行传输和交换。而基于协议的应用一般不会轻易地被历史淘汰:在过去的几十年里,基于 HTTP 上层的网站,以及技术更新换代了好几波,但底层的协议依然还是 HTTP(HTTPS)。基于 BitTorrent 协议的文件交换协议,和基于SMTP(Simple Mail Transfer Protocol)的电子邮件传输便是其中之一。

+

二. 邮件发送的流程

+

电子邮件的发送过程可以简单地描述为以下几个步骤:

+
    +
  • 用户在邮件客户端(例如Gmail)中撰写并发送一封邮件
  • +
  • 邮件客户端使用SMTP协议将邮件发送到相应的邮件服务器。
  • +
  • 通过DNS查询MX记录找到接收方的邮件服务器。
  • +
  • 发送邮件服务器使用SMTP协议将邮件传递给接收方的邮件服务器。
  • +
  • 接收方的邮件服务器将邮件存储在相应的邮箱中,供用户查看。
  • +
+

为了确保通信安全,电子邮件的发送还引入了一些安全机制,如SPF、DKIM和DMARC。

+
    +
  • SPF(Sender Policy Framework)用于验证发件人的身份,防止发件人伪造。
  • +
  • DKIM(DomainKeys Identified Mail)通过数字签名验证邮件的真实性。
  • +
  • DMARC(Domain-based Message Authentication, Reporting, and Conformance)结合了SPF和DKIM,提供了更严格的邮件验证机制。
  • +
+

三.具体流程

+

假设用户 a@gmail.com 发送一封邮件到 b@qq.com,会执行如下的流程。

+

1.查询 MX 记录

+

当我们在 Gmail 网页上撰写一封邮件,并点击发送按钮之后。Gmail 会用自己的内部协议链接 Gmail 的 Outgoing SMTP 邮件服务器。

+

Outgoing SMTP 验证用户权限,然后将邮件以 MIME 格式发送到发送队列中。

+

Gmail SMTP 服务器会通过 DNS 查询到域名 qq.com MX(Mail Exchanger) 记录(dig MX qq.com),找到邮件服务器的 IP 所在。

+

在 Linux 下也可以通过 dig mx qq.com 来查询到。这一步在对应到自建的邮件服务器的时候,就是通过配置 DNS 的 MX 记录来实现的。

+

一般情况下会配置一个 A 记录 mx.example.com 指向服务器的 IP 地址。然后再配置一个 [[MX 记录]],@ 全部域名的 MX 请求全部转发给 mx.example.com。

+

2.SMTP 发送

+

当 Gmail 的服务器找到 QQ 邮箱的 IP 地址之后,邮件就会通过 SMTP(Simple Mail Transfer Protocol ) 协议连接服务器的连接,尝试发送给 QQ 的服务器。

+

为了简化理解,SMTP 传输的时候就直接声明,我 a@gmail.com ,我要发送邮件到 b@qq.com ,内容是某某某。QQ 邮箱的服务器接收到 Gmail 的邮件之后,再根据用户名决定发给具体谁的邮箱。

+

这中间会发现不存在任何验证发送方身份的过程,这也就意味着任何人都可以伪装一个任意的发送邮箱以一个伪装的邮箱发送邮件。SMTP 最早是建立在相互信任的基础之上的,所以也给后面的恶意使用留下了一些漏洞,为了修复这个漏洞发明了 SPF。

+

3.SPF 验证

+

上文提到过 SMTP 协议发送邮件的过程中没有验证发送方,这也就意味着发信方可以任意指定发件人邮箱地址,这会存在一些安全问题。

+

具体来说,本来我的 Gmail 邮箱是 a@gmail.com,假如有不法分子,就可以利用这个漏洞,伪装成自己是 a@gmail.com 给别人发送邮件。

+

[[SPF]] 的目的就是为了防止伪造发信人。

+
    +
  • SPF 的原理
  • +
+

SPF 的实现原理非常简单,就是通过添加一条 DNS 记录。

+

如果邮件服务器收到一封来自主机 1.1.1.1 的邮件,并且发件人是 a@gmai.com,为了确认发件人,邮件服务器就会去查询 gmail.com 的 SPF 记录。如果域名设置了 SPF 记录,允许 1.1.1.1 的 IP 地址发送邮件,那么收件的邮件服务器就会认为邮件是合法的,否则就会退信。

+

有了 SPF 记录之后,如果有人想要伪装成 a@gmail.com 他既不能修改 gmail.com 的 DNS 解析,也无法伪造 IP 地址,就有效的防止了伪装。

+
    +
  • SPF 的语法
  • +
+

在自建邮件服务器的时候,经常会让我们设置一个 TXT 记录,配置值为 v=spf1 mx ~all,这表示的意思是允许当前域名的 MX 记录对应的 IP 地址。

+

下面再举个非常常见的例子:

+
v=spf1 a mx ip4:173.10.10.10 -all
+
+

表示允许当前域名配置的 A 记录,MX 记录的 IP 地址,以及一个额外的 IP 进行发信。

+
    +
  • SPF 存在的问题
  • +
+

SPF 机制可以有效地规避了发送邮件方伪造发件人的问题。但实际使用的时候,如果你使用多个邮箱,然后设置了其中 c@163.com 邮箱自动转发到 a@gmail.com 中。

+

那么这个时候如果 b@qq.com QQ 邮箱发送了一封邮件到 c@163.com 邮箱,163 邮箱原封不动地将邮件转发到 Gmail 邮箱,这个时候发件人是 b@qq.com,但是 Gmail 回去查询 qq.com 的 SPF 记录,但会发现并不包含 163 邮箱的 IP 地址,会误判转发的邮件;所以又诞生了 DKIM。

+

4.DKIM

+

DKIM (DomainKeys Identified Mail) 的缩写,允许发送者通过在邮件的 header 中包含一段数字签名来验证邮件。DKIM 使用公私密钥来确保邮件内容是从授信的邮件服务器发送的。

+

还是利用上面的例子,因为我们把所有发送到 163 邮箱的邮件都转发到了 Gmail 邮箱,所以来自 QQ 邮箱的邮件在验证 SPF 时会失败。

+

那么在 DKIM 中,发送邮件的服务器,比如 QQ 邮箱,会使用公私钥对邮件内容进行签名,并将签名和邮件内容一起发送。当 Gmail 收到从 163 邮箱转发过来的 QQ 邮箱邮件的时候,就会去查询 qq.com 的 DNS 记录,拿到公钥。然后使用公钥和签名来验证邮件内容。如果验签不通过,则将邮件判定为伪造。

+

5.DMARC

+

经过了 SPF 和 DKIM 的保证,是不是就可以完美的发送接收邮件了?其实并不能,我们通过邮件后台来看一下邮件的原始文本。

+
MIME-Version: 1.0
+Return-Path: xxx@fake.com
+DKIM-Signature: d=fake.com,b=adceabkekd12
+Date: Tue, 22 Mar 2022 06:37:58 +0000
+Content-Type: multipart/alternative;
+ boundary="--=_RainLoop_587_997816661.1647931078"
+From: admin@a.com
+Message-ID: <a67d96a38592cdad46cca89e98dda26d@techfm.club>
+Subject: Seems it works
+To: "Somebody" <a@gmail.com>
+
+
+----=_RainLoop_587_997816661.1647931078
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+~~
+
+----=_RainLoop_587_997816661.1647931078
+Content-Type: text/html; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+<!DOCTYPE html><html><head><meta http-equiv=3D"Content-Type" content=3D"t=
+ext/html; charset=3Dutf-8" /></head><body><div data-html-editor-font-wrap=
+per=3D"true" style=3D"font-family: arial, sans-serif; font-size: 13px;"><=
+br>~~<signature></signature></div></body></html>
+
+----=_RainLoop_587_997816661.1647931078--
+
+
+

SPF 解决了接收方验证发件人域名 SPF 记录内 IP 地址从而验证发件人的问题。但是因为 SPF 定义的发件人是 RFC5321 协议中规定的 Return-Path,而 DKIM 在邮件头中直接包含了域名,只要使用该域名的公钥验证通过即可。

+

而现在的邮件服务给用户展示的发件人都是 From 字段,而不是 SPF 的 Return-Path,也不是 DKIM 的 DKIM-Sginatur: d=,所以攻击者可以通过伪造这两个字段,发送如上的邮件,完美通过 SPF 和 DKIM 检查,因为 SPF 检查 Return-Path 而 DKIM 验证的 d= 也是 fake.com 所以最终用户看到的发件人却是 admin@q.com

+

所以就诞生了 DMARC。DMARC 结合了 SPF 和 DKIM,规定了 Return-Path 和 DKIM-Signature: d= 两个至少需要有一个与 From 头对应,否则判定为失败。

+

当邮件服务器接收到邮件时,先验证 DKIM,SPF,然后再根据 DMARC 的配置检查。这样就能确保最终用户看到的 From 字段和 SPF、DKIM 认证的发件人一致了。

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/network-how-email-works-2/index.html b/public/network-how-email-works-2/index.html new file mode 100644 index 0000000..5570026 --- /dev/null +++ b/public/network-how-email-works-2/index.html @@ -0,0 +1,286 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

电子邮件是如何工作的:POP3/IMAP/SMTP

+ + + + + + +
+

前言 POP3、IMAP 和 SMTP 是用于电子邮件传输的常见协议和服务,这些协议共同构成了电子邮件系统的基础,允许用户接收、发送和管理电子邮件。

+ +
    +
  1. POP3(邮局协议版本3):POP3 是一种用于接收电子邮件的协议。当你使用 POP3 时,电子邮件会从服务器下载到你的设备上,并且通常会从服务器上删除。这意味着邮件只存在于你的设备上,而不再保留在服务器上。POP3 通常用于单一设备或者设备上少量的邮件存储需求。
  2. +
  3. IMAP(互联网邮件访问协议):IMAP 也是一种用于接收电子邮件的协议,但它与 POP3 不同的是,IMAP 允许邮件保留在服务器上,并且同步到多个设备上。这意味着无论你使用哪个设备访问邮件,都能看到同样的邮件状态,包括已读、未读、已删除等。IMAP 适用于需要在多个设备之间同步邮件的情况,例如在手机、平板电脑和台式电脑之间。
  4. +
  5. SMTP(简单邮件传输协议):SMTP 是用于发送电子邮件的协议。当你发送一封电子邮件时,你的邮件客户端会使用 SMTP 协议将邮件发送到电子邮件服务器。SMTP 负责将邮件从发送者的电子邮件客户端传送到接收者的邮件服务器。SMTP 是一个推送协议,它将邮件推送给服务器,而不是拉取邮件。
  6. +
+

这是每个协议的简要技术原理:

+

POP3(邮局协议版本3)

+
    +
  • 客户端连接到邮件服务器上的 POP3 端口(通常是 110 端口)。
  • +
  • 客户端发送身份验证信息(通常是用户名和密码)以登录到邮箱。
  • +
  • 一旦登录成功,客户端可以请求收件箱中的邮件列表。
  • +
  • 客户端可以选择下载邮件到本地设备。
  • +
  • 下载的邮件通常从服务器上删除,但可以根据设置保留一份副本。
  • +
  • 客户端可以选择在下载后删除邮件,或者在稍后删除它们。
  • +
+

IMAP(互联网邮件访问协议)

+
    +
  • 客户端连接到邮件服务器上的 IMAP 端口(通常是 143 端口)。
  • +
  • 客户端发送身份验证信息(通常是用户名和密码)以登录到邮箱。
  • +
  • 一旦登录成功,客户端可以请求收件箱中的邮件列表,以及邮件的状态信息(如已读、未读、已删除等)。
  • +
  • 客户端可以选择下载完整的邮件或邮件的部分内容到本地设备,同时保留邮件在服务器上的副本。
  • +
  • 客户端对邮件的操作(如标记为已读、移动到文件夹等)将反映在服务器上,从而在其他设备上同步。
  • +
+

SMTP(简单邮件传输协议)

+
    +
  • 客户端连接到邮件服务器上的 SMTP 端口(通常是 25 端口)。
  • +
  • 客户端发送邮件内容和邮件头信息(如发件人、收件人、主题等)给服务器。
  • +
  • 服务器接受邮件,并将其转发到接收者的邮件服务器。
  • +
  • 接收者的邮件服务器接收邮件,并将其存储在相应的收件人邮箱中。
  • +
  • SMTP 是一个简单的推送协议,它负责将邮件从发送方传送到接收方,但不涉及接收方对邮件的确认或响应。
  • +
+

它们的区别和共同点:

+

区别:

+

功能:

+
    +
  • POP3 主要用于从邮件服务器上下载邮件到本地设备,通常会将邮件从服务器上删除。
  • +
  • IMAP 允许用户在多个设备之间同步邮件状态,并且邮件保留在服务器上。
  • +
  • SMTP 用于发送电子邮件。
  • +
+

邮件管理:

+
    +
  • POP3 在客户端下载邮件后通常会将邮件从服务器上删除,因此邮件只存在于本地设备上。
  • +
  • IMAP 允许邮件在多个设备之间同步,因为邮件保留在服务器上。
  • +
  • SMTP 不管理邮件存储,它只是负责将邮件从发送方传送到接收方。
  • +
+

端口号:

+
    +
  • POP3 默认端口号是 110。
  • +
  • IMAP 默认端口号是 143。
  • +
  • SMTP 默认端口号是 25。
  • +
+

操作方式:

+
    +
  • POP3 是拉取协议,客户端需要主动连接到服务器并拉取邮件。
  • +
  • IMAP 是双向同步协议,客户端与服务器之间进行交互,可以同步邮件状态。
  • +
  • SMTP 是推送协议,用于将邮件从发送方传送到接收方。
  • +
+

共同点:

+
    +
  • +

    用途::它们都是用于电子邮件传输的标准协议。

    +
  • +
  • +

    与邮件服务器的通信::它们都涉及客户端与邮件服务器之间的通信。

    +
  • +
  • +

    身份验证::它们都需要用户身份验证来访问邮箱。

    +
  • +
+

一次完整的邮件通信过程

+

发送方(发件人):

+
    +
  • +

    撰写邮件: 发件人使用邮件客户端(如Outlook、Gmail等)撰写邮件,并填写收件人的电子邮件地址、主题和邮件内容。

    +
  • +
  • +

    SPF 检查: 发送邮件服务器可能会执行 SPF(Sender Policy Framework)检查。它查询发件人域名的 DNS 记录,以确认发送邮件的服务器是否被授权发送邮件。

    +
  • +
  • +

    DKIM 签名: 发送邮件服务器对邮件进行 DKIM(DomainKeys Identified Mail)签名。它使用发件人域名的私钥对邮件进行加密签名,以确保邮件内容在传输过程中不被篡改。

    +
  • +
  • +

    SMTP 发送邮件: 发送邮件服务器使用 SMTP(简单邮件传输协议)将邮件发送到接收邮件服务器。SMTP 服务器与接收邮件服务器之间建立连接,并通过指定的端口(通常是 25 端口)传输邮件。

    +
  • +
+

接收方(收件人):

+
    +
  • +

    SMTP 接收邮件: 接收邮件服务器接收到发送方发送的邮件。SMTP 协议负责将邮件从发送方传输到接收方。

    +
  • +
  • +

    SPF 验证: 接收邮件服务器执行 SPF 验证,检查发送方服务器的 IP 地址是否在发件人域名的 SPF 记录中被授权发送邮件。

    +
  • +
  • +

    DKIM 验证: 接收邮件服务器对收到的邮件执行 DKIM 验证。它使用发件人域名的公钥来验证邮件的 DKIM 签名,以确保邮件内容的完整性和真实性。

    +
  • +
  • +

    DMARC 检查: 如果接收邮件服务器支持 DMARC(Domain-based Message Authentication, Reporting, and Conformance),它会执行 DMARC 检查。DMARC 结合了 SPF 和 DKIM,允许域名所有者指定如何处理未通过验证的邮件。

    +
  • +
  • +

    投递邮件到邮箱: 如果邮件通过了所有的验证步骤,并且没有被识别为垃圾邮件,接收邮件服务器将把邮件投递到收件人的邮箱中。

    +
  • +
+

邮件获取(收件人):

+
    +
  • +

    POP3 获取邮件(可选): 收件人可以使用 POP3(邮局协议版本3)从邮件服务器上下载邮件到本地设备。POP3 客户端通过指定的端口(通常是 110 端口)连接到邮件服务器,并下载邮件到本地设备上。根据设置,邮件可能会从服务器上删除。

    +
  • +
  • +

    IMAP 获取邮件(可选): 收件人可以使用 IMAP(互联网邮件访问协议)从邮件服务器上获取邮件。IMAP 允许邮件保留在服务器上,并且在多个设备之间同步邮件状态。IMAP 客户端通过指定的端口(通常是 143 端口)连接到邮件服务器,并获取邮件列表和邮件内容。

    +
  • +
+

这是一个完整的双向邮件通信过程,包括了 SPF、DKIM、DMARC,以及 POP3、IMAP、SMTP 协议的作用。这些技术和协议共同构成了电子邮件系统的基础架构,保障了邮件的传输安全性和可靠性。

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/network-how-email-works-3/index.html b/public/network-how-email-works-3/index.html new file mode 100644 index 0000000..62d0969 --- /dev/null +++ b/public/network-how-email-works-3/index.html @@ -0,0 +1,246 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

电子邮件是如何工作的:自建域名邮箱

+ + + + + + +
+

前言 poste.io 邮件服务基于 Docker 搭建,用的是 Haraka + Dovecot + SQLite 邮件系统,占用资源较少,安装简单,适合个人使用。

+

VPS上的配置

+

修改VPS hostname

+
hostnamectl set-hostname mail.your-domain.com
+
+

修改hosts文件

+
vim /etc/hosts
+
+

添加一行

+
127.0.1.1 localhost.localdomain mail.your-domain.com
+
+

安装poste

+

docker compose文件示例:

+
version: '3.7'
+
+services:
+  mailserver:
+    image: analogic/poste.io
+    hostname: mail.your-domain.com
+    ports:
+      - "25:25"
+      - "110:110"
+      - "143:143"
+      - "587:587"
+      - "993:993"
+      - "995:995"
+      - "4190:4190"
+      - "465:465"
+      - "127.0.0.1:8808:80"
+      - "127.0.0.1:8843:443"
+    environment:
+      - LETSENCRYPT_EMAIL=admin@your-domain.com
+      - LETSENCRYPT_HOST=mail.your-domain.com
+      - VIRTUAL_HOST=mail.your-domain.com
+      - DISABLE_CLAMAV=TRUE
+      - TZ=Asia/Shanghai
+      - HTTPS=OFF
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ./mail-data:/data
+
+
    +
  • +

    禁用反病毒功能(DISABLE_CLAMAV=TRUE)、禁用反垃圾邮件功能(DISABLE_RSPAMD=TRUE),可以大幅减低内存和CPU占用,请酌情设置禁用选项。

    +
  • +
  • +

    禁用WEB收发功能(DISABLE_ROUNDCUBE=TRUE),可以进一步减少资源占用,不过非必要不建议禁止。

    +
  • +
  • +

    8808为http端口,可以根据自己的需求修改。

    +
  • +
+

Dns配置

+ + + + + + + + + +
记录类型主机记录记录值
Amail1.2.3.4 (your ip)
MXyour-domain.commail.your-domain.com
TXTyour-domain.comv=spf1 mx ~all
TXT_s20160910378._domainkey.your-domain.comk=rsa;p=MII.........
TXT_dmarcv=DMARC1; p=none; pct=100; rua=mailto:mail@your-domain.com
CNAMEimapmail
CNAMEsmtpmail
CNAMEpopmail
+

最后还需到 VPS 服务商处添加一个反向 DNS,也就是 rDNS 解析,把 IP 解析到 mail.your-domain.com 这个域名,有些 VPS 商家不提供这种服务,所以需要选择好VPS服务商。

+

配置poste

+

通过浏览器访问https://mail.your-domain.com/admin/login进入poste.io的配置页面,按照提示进行配置,然后点击 Generate new key,生成 key,添加到 DNS 解析记录,就是上面最后一条解析_s20160910378._domainkey.your-domain.com

+

第三方客户端 SMTP/IMAP/POP3 配置

+

搭建完毕之后我们也可以通过客户端软件连接到我们的邮箱,如thunderbird.

+ + + + +
协议服务器地址端口SSL
SMTPmail.your-domain.com, smtp.your-domain.com25, 465, 587STARTTLS
IMAPmail.your-domain.com, imap.your-domain.com993, 143STARTTLS
POP3mail.your-domain.com, pop.your-domain.com995, 110STARTTLS
+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/network-isps/index.html b/public/network-isps/index.html new file mode 100644 index 0000000..67202dc --- /dev/null +++ b/public/network-isps/index.html @@ -0,0 +1,509 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

Network的艺术:国内至国际骨干ISP线路整理

+ + + + + + +
+

前言 本文主要探讨的是IPv4网络,国际出口线路的质量分析以及各大ISP的介绍。

+

运营商线路概览

+

中国电信

+
    +
  • +

    163骨干网(ChinaNet):走AS4134路由节点,IP开头一律是“202.97..”,全程不经过CN2网络节点,已知出口有:北京、上海、广州

    +
  • +
  • +

    CN2:中国电信下一代承载网,简称CN2;CN2分为CN2 GT和CN2 GIA:

    +
      +
    • CN2 GT(Global Transit 又称半程 CN2 )国内走163骨干网,国际走CN2.
    • +
    • CN2GIA (Global Internet Access 又称纯 CN2/全程 CN2)全程不经过163骨干网,走AS4809路由节点,IP开头一律是“59.43..”,已知出口:北京、上海、广州、乌鲁木齐.
    • +
    +
  • +
+

中国联通

+
    +
  • +

    联通169网络(CHINA169):由原中国网通互联网骨干网(CHINA169)和原中国联通互联网骨干网(UNINET)合并而来,全程走AS4837的路由节点,IP开头一律是“219.158..”,已知出口:北京、上海、广州

    +
  • +
  • +

    联通A网(CUII)经常被称为9929网络:走AS9929路由节点,IP开头一律是“218.105../210...*”,对标电信CN2 GIA,已知出口:北京、上海、广州

    +
  • +
  • +

    联通国际CUG:走AS10099路由节点,提供至大陆方向的差异化接入,包括 CUG(AS10099 -> AS4837)和 CUG VIP(AS10099 -> AS9929 -> AS4837)

    +
  • +
+

联通的线路组合主要有以下几种:

+
    +
  • 内地 AS4837 + 境外 AS4837:最普通、最常见的联通 169 网络,也是一般联通家宽路由线路。
  • +
  • 内地 AS4837 + 境外 AS10099:应该算是高端线路,目前看到搬瓦工香港 CN2 GIA 是这样走的。
  • +
  • 内地 AS9929 + 境外 AS4837:目前暂时没看到这种路由,但是看到介绍说部分地区 A 网出境后会并入 169 网。
  • +
  • 内地 AS9929 + 境外 AS10099:联通高端线路,China Unicom Premium。
  • +
+

中国移动

+
    +
  • +

    中国移动骨干网:国内必走AS9808路由节点,IP开头一律是“221.176../221.183..”,部分会并入到原铁通 AS9314 / 电信 163 骨干网 / 联通 169 骨干网,已知出口:北京、上海、广州

    +
  • +
  • +

    国际段骨干网(CMI):AS58453路由节点,承接所有AS9808出镜流量

    +
  • +
  • +

    中国教育网:走AS4538路由节点,各大高校的校园网和部分大型国内云服务提供商,已知出口:北京清华大学

    +
  • +
+

使用NextTrace追踪线路

+

NextTrace 是一款开源的可视化路由跟踪(Traceroute)工具,支持 IPv4/IPv6,以及 ICMP、TCP、UDP 多种协议,可生成终端表格、JSON 输出,甚至可在线展示地图路径。它兼顾了轻量化与可视化展示的需求,非常适合网络工程师和运维人员进行链路排查与延迟分析。

+
+

Ntrace-core

+
+

基本用法示例

+
# IPv4 ICMP 路由跟踪
+nexttrace 8.8.8.8
+
+# 指定输出为 JSON
+nexttrace --json www.google.com
+
+# TCP 路由跟踪到 443 端口
+nexttrace --tcp --port 443 2001:4860:4860::8888
+
+# 开启多探测包和并发
+nexttrace --queries 3 --parallel-requests 4 example.com
+
+# 显示表格输出并关闭反向解析
+nexttrace --table --no-rdns www.example.org
+
+

示例

+
❯ nexttrace 38.207.170.5x
+NextTrace v1.4.0 2025-04-16T01:10:07Z dccc41b
+[NextTrace API] preferred API IP - 198.18.0.61 - 601.41ms - 🐠 (Relay) → Misaka.HKG
+IP Geo Data Provider: LeoMoeAPI
+traceroute to 38.207.170.5x, 30 hops max, 52 bytes payload, ICMP mode
+1   192.168.1.1     *                         RFC1918
+                                              3.80 ms / 2.75 ms / 3.37 ms
+2   192.168.0.1     *                         RFC1918
+                                              4.14 ms / 5.40 ms / 6.76 ms
+3   100.64.0.1      *                         RFC6598
+                                              11.22 ms / 12.22 ms / 13.40 ms
+4   *
+5   *
+6   *
+7   *
+8   202.97.66.213   AS4134   [CHINANET-BB]    中国 广东 广州  www.chinatelecom.com.cn
+                                              22.25 ms / 21.00 ms / 20.69 ms
+9   *
+10  218.30.53.134   AS4134   [CHINANET-US]    美国 加利福尼亚 洛杉矶 CT-POP-Zenlayer www.chinatelecom.com.cn  电信
+                                              174.40 ms / 173.56 ms / 173.49 ms
+11  10.163.0.2      *                         RFC1918
+                                              173.78 ms / 174.93 ms / 174.35 ms
+12  *
+13  38.207.170.5x   AS979                     美国 加利福尼亚州 洛杉矶  as979.net
+                                              176.31 ms / 177.14 ms / 174.71 ms
+MapTrace URL: https://assets.nxtrace.org/tracemap/30cce0c3-18a6-582c-8679-xxxxxxxxxx.html
+
+
+

各种线路详解

+
    +
  • +

    BGP专线:简单来说BGP线路就是一个能够动态切换的线路,当一条线不能正常链接访问时,自动切换到另一条线路。BGP线路简单来说就是将电信、联通、移动、铁通、教育网等多家运营商的网络融合在一起的线路,融合为一个IP地址,路由器根据相关数据进行解析,选出最快的线路反馈回去,以实现不同线路之间的互联互通。

    +
  • +
  • +

    CN2:CN2线路是中国电信推出的一种优质线路,又叫中国电信下一代承载网。是中国电信目前推出的质量最好的网络带宽线路。主要特点:低丢包、低延时、轻负载,出国回国必定经过北京/上海/广州。

    +
  • +
  • +

    CN2 GT: CN2里属于Global Transit的产品(又名GIS-Global Internet Service),在CN2里等级低,省级/出国节点为202.97开头,国际骨干节点有2~4个59.43开头的CN2节点。在出国线路上拥堵程度一般,相对于163骨干网的稍强,相比CN2 GIA,性价比也较高。出国前走的是163骨干网,出国后走的是59.43开头的

    +
  • +
  • +

    CN2 GIA: CN2里属于Global Internet Access的产品,等级最高,省级/出国/国际骨干节点都以59.43开头,全程没有202.97开头的节点。在出国线路上表现最好,很少拥堵,理论上速度最快最稳定,当然,价格也相对CN2 GT偏高。

    +
  • +
  • +

    IPLC和IEPL

    +
      +
    • +

      IPLC是英文词组”International Private Leased Circuit” 的缩写,即“国际专线”,是指用户专用的跨国的数据、话音等综合信息业务的通信线路。通俗地说,也就是指传统的专线,如DDN、E1等,用于互连两点之间的通信,只不过IPLC是跨国跨境专用的而已。比如深港IPLC,即深圳到香港点对点传输而不经过公网,是完全的内网,可以被认为是真正意义上的专线。这种专线因为没有走公网因此完全不过墙,你传输什么 GFW 都是不会知道的。

      +
    • +
    • +

      IEPL是英文词组“International Ethernet Private Line”的缩写,即“国际以太网专线”。IEPL线路为二层的电路,主要为跨国性企业提供高品质的以太网专线服务。国际以太网专线服务(IEPL)为一个端对端的管理式频宽服务方案,透过网络平台,为客户提供可作无限扩充的点对点专用跨境通讯服务。IEPL网络传输性能优于专线IPLC,但是价格也比IPLC一般企业和个人用户更贵,IPLC和IEPL专线使用体验差别不大,IPLC性价比更高。个人使用。IPLC比IEPL对于企业实时合作办公络游戏加速的高端用户来说,专线更划算,IEPL专线会有比IPLC低延迟体验更好。

      +
    • +
    +
  • +
  • +

    QoS是什么?

    +
  • +
+

QoS(Quality of Service)是一种网络技术也可以理解为数据的分拣中心,用于在网络上为不同的应用程序或用户提供不同的服务质量。它可以确保网络上的数据传输是可靠的,并且可以根据需要分配带宽和优先级。简单的理解就是在上网高峰期,它会选择性丢包,确保重要客户或者重要信息优先通行,例如在上网高峰期一般个人用户和企业用户,企业用户的优先级就高于我们个人用户,跟银行的VIP客户原理一样。

+

常见地区

+

中国香港地区

+
    +
  • +

    常见运营商:CMI、CUG、NTT、PCCW、Telia、Telstra、CHT、HKBN、HKT、WTT、HGC、GTT、TaTa、HE、Cogentco、SingTel

    +
  • +
  • +

    常见数据中心:HKIX、EIEHKG(Equinix Internet Exchange HongKong)

    +
  • +
  • +

    常见下游:Cloudflare、Amazon、Azure、Google、CDN77、Cera Network

    +
  • +
+

对于很多南方地区的用户来说,对于需要访问一些全球类的网站,离得最近的CDN网络都是在香港(延时最低)。香港机房一直都是很多面向亚太地区服务器托管商的兵家必争之地,所以也涌现出了大量的IDC商家,可惜鱼目混杂,能做到价格便宜且到国内直连的却少之又少,直连高昂的宽带单价也劝退了大部分商家。

+
    +
  • CMI – 移动自己的国际骨干网
  • +
+

由于CMI自己也在卖香港资源,所以有些下游会选择直接购买CMI的Transit,来获得高Qos的CMI体验,这样国内用户到这些下游提供商就可以全部走移动的骨干网,来获得高性价比且高质量的访问体验。

+
+

境内连接质量:非常高,只要对方下游接入了足够的CMI Transit宽带,峰值宽带基本是移动保证的。无论是电信、联通还是移动(当然移动用户访问过去,优先级是最高的)。虽然高性价比,但是毕竟是香港地区,流量单价依旧远超美欧Transit的单价。

+
+
    +
  • CUG – 联通自己的国际骨干网
  • +
+

同移动的CMI,联通也卖香港资源(自治系统编号AS10099),很多下游也选择接入了CUG的资源,这对于联通用户来说,等于获得了很好的质量保证。

+
+

境内连接质量:非常高,只要对方下游接入了足够的CUG Transit宽带,峰值宽带基本是联通保证的。无论是电信、联通还是移动(当然联通用户访问过去,优先级是最高的)。

+
+
    +
  • NTT(香港)
  • +
+

可直连的国内骨干网:AS4809、AS58453

+

在香港地区,只有电信CN2、移动可以直连,其中电信CN2买了NTT Transit 。其余电信163和联通169都会绕路日本和美国。

+

移动如果不买他们的商业高Qos宽带,在高峰时期直连NTT会被Qos,丢包和延时都会显著增加,速度一般无法超过10Mbps。对于高Qos的移动用户也并不乐观,高峰时期,因为上海和广州地区汇聚层拥堵显著,所以最高速率往往也无法超过200Mbps;特殊CM2精品网大客户除外,因为你加钱买了VIP。

+
+

连接质量:需要注意的是,CN2很多时候不是万能的,特别是香港地区。CN2到香港NTT不可靠,有时候会爆炸,延时会呈现剧烈的抖动,如果需要追求高稳定性,不推荐CN2用户使用接入香港NTT的网络。

+
+
    +
  • PCCW(香港)/HKT
  • +
+

可直连的国内骨干网:AS4134、AS4809、AS4837、AS9929、AS58453

+

我们平时接触PCCW的机会很多,PCCW也有一个负责国际优化的网络PCCWG (G=Global),我们平时遇到的商家一般接入的都是PCCW(非含G的网)。其实PCCW的效果在平时是被夸大的,就算是线路可以直连实际综合连接效果也仅仅是一个平均水平。

+

电信163(AS4134)到香港PCCW是否直连看本地电信网络是否有自己的AS号,比如北京电信的AS4847城域网,上海电信的AS4812城域网等。一般来说,如果该地网络有自己的城域网AS号专门管辖,除非商家有特别优化,那么一般到香港PCCW不直连,否则如果是直接位于AS4134上一般会直连。电信网络到PCCW一般只有北京和广州两个汇聚层可达,上海汇聚层不可达,高峰丢包较高,速度不理想。

+

联通169(AS4837)联通到香港PCCW可能绕美,原因和电信部分相同,不再赘述。直连的情况下,联通到PCCW效果要远远好于电信,处于可用的状态。

+

联通A网(AS9929) 网络质量基本是这么多网络里面连接到PCCW最好的,延时抖动也是最低的。但是9929的价格比CN2都要贵上好多倍,一般没有点钞能力是用不上的…

+

移动的CMI(AS58453),如果没有商家优化,移动会随机把路由发往美国、日本、香港三地,以实现流量平衡,在用户看来,这就导致延时时高时低,非常不稳定,不推荐移动使用。

+

同时,HKT隶属于PCCW,所有的国际出口都是走PCCW/PCCWG的。HKT因为可以走上PCCWG和德国地区直连,所以也被称之为打机神线。但是普通的HKT家宽/静态根据段不一样,联通169可能绕韩国KT,也有可能直连(联通9929通过PCCW与HKT互联)。

+
    +
  • CHT(香港)
  • +
+

可直连国内骨干网:AS4134、AS4837、AS58453

+

CHT即中华电信,为中国台湾的第一大运营商,拥有2大骨干网(CHW「 HINET」、TWGATE),我们通常说的Hinet即为CHW网络,CHW与TWGATE的关系可以参照电信163和CN2的关系。

+

事与愿违,不知道开始,电信163骨干网到CHW网络的效果急转直下,无论是低峰还是高峰的下载速度都只能用惨淡来形容。所以除非你有业务需求,否则我不推荐你把个人网站放在CHW下,高昂的成本价格现在无法匹配上其延时和速度,是个性价比很低的选择。

+

相比于电信163的拉垮表现,联通169的表现就漂亮的多,差不多的延时却有着更低的丢包,更高的峰值速度。但是鉴于该地区很高的主机售价,如果你是一个联通用户,CHW也未必是最佳的选择。

+

也别对移动CMI抱有太大的期望,在低峰和高峰表现截然不同,高峰常常极度拉垮,上面的Telstra好歹还是有速度,这个是真的一点速度都跑不出来,不推荐。

+

中国台湾地区

+
    +
  • +

    常见运营商:HiNet、TFN(台湾固网)、SeedNet、TaNet(台湾学术网络)、HomePlus(中嘉宽频)

    +
  • +
  • +

    常见数据中心:TWIX

    +
  • +
  • +

    HINET

    +
  • +
+

可直连国内骨干网:AS4134、AS58453、AS4837

+

其中 电信 和 联通 延迟都明显要比移动高一些。

+

HiNet是中华电信(CHT)的一个品牌,也是全台湾最大的宽带提供商。目前台湾地区的主流流媒体解锁都是用了HiNet动态IP(家宽)以及静态IP(商宽、IDC)来解锁的。HiNet拥有整个台湾地区最大的电信骨干网,也是国内出口流量最大的ISP。CHT另拥有一张TWGate的网络,专注国际互联,其性质相当于中国电信的CN2。

+

日本

+
    +
  • +

    常见运营商:NTT、IIJ、KDDI、BBTEC、Telstra、PCCW、BGP.NET

    +
  • +
  • +

    常见数据中心:JPIX、BBIX、EIEHND(Equinix Internet Exchange Tokyo)

    +
  • +
  • +

    常见下游:Cloudflare、Amazon、Azure、Google、M427、xTom(搬瓦工是他的下游)

    +
  • +
+

日本的宽带业务竞争激烈,导致ISP提供商不得不杀出更低的价格来吸引客户,但是往往事与愿违——用户的口碑却更糟糕了。比如,和阿里巴巴合资的SoftBank(软银)公司创立的ISP服务商——BBTEC,看起来是一个不错的选择,实际晚高峰网络拥堵,体验很差劲。

+

不仅是家宽,商宽乃至服务器机房,接入一条ISP线路的成本价格都不菲,况且很多日本IDC只对日本本国居民提供服务,所以催生了很多代办业务,最有名的就是樱花机房的服务器代办服务。往往只有这些对本土开放的IDC才有可能是原生IP(可以解锁当地的众多流媒体、游戏和网站)。

+
    +
  • NTT
  • +
+

可直连国内骨干网:AS4134、AS4809、AS4837、AS9929、AS58423

+

日本作为NTT的大本营,几乎全国的宽带服务提供商都有NTT的踪迹。因为NTT的骨干网覆盖了日本几乎所有能够覆盖到的地区。

+

NTT和国内ISP互联时间很早,在2000年后,NTT和当时的网通互联,互联出口设在上海和北京,并在上海和北京分别建设NTT的PoP节点(少数国外ISP将PoP设在国内的案例)。

+

值得一提的是,但是这是目前国内直连日本NTT延时很低且很稳定的渠道,CN2到日本NTT都干不过它,根据实测,目前NTT-9929的速度基本取决于用户接入的9929的带宽速度。

+

中国电信163和日本NTT之间的扩容就勤快多了,电信还在日本东京设立了PoP方便和日本本土ISP快速互联。听起来很美好是吗?但是这不妨碍电信163和日本NTT之间日常大爆炸(里面大部分都是被巨量的DDOS流量打崩的)。

+
    +
  • IIJ
  • +
+

可直连骨干网:AS4134、AS4837、AS58423

+

中国电信的163与IIJ的互联是通过电信在东京的PoP实现的,国内可以通过三大汇聚层轻松访问PoP节点。互联的网络质量远好于和NTT的质量。IIJ是电信163用户造访日本网站最好的线路之一,目前已经胜过软银,不考虑高峰丢包和延时抖动,是性价比之选。

+

中国联通169与IIJ的互联方式和电信几乎一样,但是综合来看要好于163与IIJ互联的质量。提供IIJ接入的IDC价格比较亲民的很多,如果不愿意接受软银的高价位的话,那就上IIJ吧。

+

目前移动和IIJ的互联已经通过东京移动的PoP来完成,故移动到日本IIJ不再绕香港而是通过NCP海缆直连东京的PoP后与IIJ完成互联,上海移动到东京IIJ参考延时为45ms(网上查的)。

+

综上,IIJ是日本地区对我们比较友好的,也是价格相较于其他三家比较实惠的一家ISP,如果没有太小众化的需求,上国内走IIJ的VPS是很省心的选择。

+
    +
  • BBTEC(软银)
  • +
+

可直连骨干网:AS4134、AS4837、AS9929、AS58423

+

BBTEC(软银)其实是近几年才被我们注意到的一家ISP,在上海地区设有PoP并与电信163和联通169/9929互联。该线路一直被称之为联通到日本最好的线路之一。

+

想要补充一点的是,9929早期和软银并没有直连Peer,而是借助4837(联通169)作为跳板实现的。而近期在路由测试中,我们可以清楚地看到软银和9929已经在上海PoP实现互联,但是在BGP ToolKit上都未显示2者有任何形式的互联,基本可以判断是Private Peer。

+

电信163到软银延时相比于NTT属实较低,但是却同样跑不出什么速度来,延时最初是日本御四家里最低的,但是后来因为使用人数的增加,延时逐渐不如IIJ。

+

联通169到软银的延时则相对不稳定,取决于去程走上海口和北京口,通常BBTEC回程经由自己的上海POP与联通互联。尽管联通和软银互联的优势已经不如以前,但是目前仍旧是联通到日本最好的线路之一。

+

联通9929到软银的延时稳定,互联速度也取决于用户接入的9929带宽速度。

+

如今,移动已经在日本的东京设立了PoP,所以从回程看,除了广州移动还是继续走香港CMI,其余均在日本就Peer,并由移动自己的骨干网负责流量回国承载。目前去程依旧全部绕香港CMI,这也导致北方移动延时的升高。总体来说,软银对北方移动不友好。

+

新加坡区域

+
    +
  • +

    常见运营商:NTT、Singtel、Telstra、StarHub、MyRepublic、PCCW(G)、Cogentco、HE、Tata、CMI、CUG、BGP.NET、SG.GS

    +
  • +
  • +

    常见数据中心:SGIX、EIESG(Equinix Internet Exchange Singapore)

    +
  • +
  • +

    下游:OVH、Cloudflare、Google、Amazon

    +
  • +
  • +

    NTT(新加坡)

    +
  • +
+

可直连国内骨干网:AS4134、AS58453

+

正如你所见,NTT在亚太地区无处不在~ 所以我们一般把NTT视作亚太地区ISP的标杆,这已经成为了事实上公认的标准。

+

在新加坡,NTT也拥有巨量的骨干资源,轻松连接新加坡所有的本地ISP。NTT也有多条新加坡至日本的海底光缆所有权/使用权,所以NTT可以借新加坡作为跳板,以此连接马来西亚、菲律宾、印度尼西亚、泰国、越南、缅甸、柬埔寨、印度等国。

+

中国电信163与2020年和NTT在新加坡正式建立互联,即意味着新加坡NTT从即日起无需绕行日本再与163骨干网互联,但是情况变得更加糟糕,因为新加坡地区的中国电信163和NTT互联宽带很小,所以几乎全天都处于被塞满的状态,延时异常偏高,丢包率极大,因此非常不推荐使用163连接新加坡地区的NTT。

+

移动的CMI在新加坡有自己的PoP,同时在当地就可以和NTT互联,因互联宽带很大,所以目前没有看到被塞爆的情况,移动用户目前访问新加坡地区资源的主流渠道就是通过新加坡PoP。

+

联通9929和联通169目前都不能直连新加坡NTT,请详见上面的日本NTT。

+

韩国

+
    +
  • +

    常见运营商:KT、SKT、LG (绕路的ISP:NTT、PCCW、Telstra Global 绕日绕港绕新加坡 故不测试)

    +
  • +
  • +

    常见数据中心:KINX

    +
  • +
  • +

    常见下游:Moack、Oracle、Cloudflare、Amazon、Azure

    +
  • +
+

韩国本土网络发达,除了三大ISP以外还有地区性ISP,大陆地区前往韩国主要走TPE、APG、APCN-2、NCP四大海缆。

+

国际路由差强人意,但靠着CDN也足够应付。但到中国大陆的带宽与路由不尽人意,绕路与直连汇聚层日常性堵塞层出不穷,丢包与抖动比较严重(虽然没有到163-NTT那么夸张)。

+

同时韩国的互联网管理相对严格,购买上比较麻烦(建议别买,没啥必要)。

+
    +
  • KT
  • +
+

可直连骨干网:AS4134、AS4809、AS4837、AS9929、AS58453

+

KT(Korea Telecom),韩国最大电信运营商,市场占有率排名第一。

+

英雄联盟里KT战队的赞助商,就是他,你如果打LOL就对这个名字很眼熟.

+

目前电信163/CN2和韩国KT之间的互联是通过APG海缆完成的,因为APG海缆只在上海有登陆,所以目前前往韩国KT都是走上海出口。

+

电信163至韩国KT的速度在Peer不被塞满的情况下单线程能跑100-200Mbps,晚高峰受限于汇聚层和Peer宽带的双重因素影响,速度受限比较严重。CN2虽然不用太担心汇聚层的拥塞问题,但是目前的Peer宽带依旧是比较主要的速度和延时等稳定性制约因素。

+

联通9929与KT有互联,同样也是走上海出口。高峰期几乎无丢包,延迟极低,单看极限最低延迟逼近沪韩IPLC;可惜经常抖动,虽然幅度非常小。速度方面也属于跟日本ISP到9929一样,KT到9929的速度取决于用户接入的9929带宽速度。

+

欧洲

+
    +
  • DTAG
  • +
+

可直连骨干网: AS4134、AS4837、AS9929

+

Deutsche Telekom AG ,德国电信,德国第一大ISP,T1级。旗下移动运营商T-mobile相比于DTAG更加知名。

+

DTAG于AS4134和AS4837均有peer。同时也是AS9929上游。但延迟均200+起跳。

+

电信163普通家宽会被强制丢包,而163plus能保证相对稳定延迟与相对较低的丢包

+

联通169则取决于汇聚层是否拥塞。非拥塞状态则能保证网络质量。但是只限于北方地区的联通。

+

南方地区的联通将会被无慈悲的绕美。

+

AS9929依旧稳定发挥,甚至延迟优于AS4134 AS4837,但速度很勉强,几乎稳定80Mbps。

+
    +
  • Cogent Communications
  • +
+

可直连骨干网:AS4134、AS4837、AS9929、AS58453。

+

Cogentco由于在Traceroute上的细节写的过于清楚明白,以至于有一部分以为跳数越多越差人觉得Cogentco不行。虽然它也确实不太行…

+

Cogentco,联通9929真正的互联主力……几乎绝大部分的欧美线路到9929都会被Cogentco宣告。以至于在欧洲会出现回程不走DTAG硬是跑Cogentco

+

外加联通9929的NOC基本不会主动调整欧美路由。速度十分玄学,单线程在50Mbps摇摆,多线程却接近跑满。

+

美国

+

洛杉矶和圣何塞是美西重要的面向亚太地区的互联网PoP中心,TPE海缆多从此处2点接入。中美之间的互联占据了出境流量很大的一部分,也是电信163出国的主要路径。

+
    +
  • HE
  • +
+

可直连骨干网:AS4134、AS4837、AS58453

+

HE,全称为 Hurricane Electric(飓风电气),目前是坐拥全球以Peer数量计算的最大IPv6骨干网的ISP,骨干网自治编号为AS6939。HE也提供免费的IPv6 Tunnel,以方便IPv4单栈的用户能够无障碍地访问IPv6网络。

+

我们看到的亚太地区(香港、新加坡)的低价VPS产品线,几乎都一致地选择了HE作为唯一的互联网接入,而且接入的宽带并不大,平均1Gbps。但是哪怕是HE这样的ISP,在亚太地区的BGP Transit也颇为昂贵,这些商家为了能够有所盈利,在超低的VPS价格上,宽带上面必须大幅超售。

+

电信163和HE在洛杉矶有10~20G的互联,平时鲜有出现较大的延时抖动,但是速度限制较为严重。

+

联通169和HE的洛杉矶互联通常被视为在廉价互联里面很具有性价比的,相比于联通169和GTT的互联,和HE的互联质量就要好很多,很多用户也在尽可能选择更价廉物美的选择。

+

CMI与美西的互联一向较差,并不具有较好的连通性,再加上HE和CMI的互联本身就炸的比较厉害,所以CMI就拉倒吧。

+
    +
  • GTT
  • +
+

可直连骨干网:AS4134、AS4837、AS58453

+

GTT,前身为Global Telecom and Technology,自1998年成立以来,在跨国电信业务上耕作至今。

+

联通169在美西较大地依赖GTT的互联,导致延时相比正常美西延时高很多,速度并不乐观。

+

电信163和GTT的互联却是出乎意料的好,根据SmokePing的结果,电信163和GTT的互联全天几乎不丢包,完全受限于汇聚层是否通畅。这就意味着只要使用高Qos的电信宽带就可以获得较好的速度。

+
    +
  • Telia
  • +
+

可直连骨干网:AS4134、AS4809、AS4837、AS58453

+

Telia是瑞典最大的电话和电信通讯公司,前身为瑞典电报局及芬兰电讯。现更名为Arelion,但目前在路由上的名称依旧是Telia。

+

Telia在美国、欧洲都有和电信163互联,总体来说是很中规中矩的线路。

+
    +
  • Cogent Communications
  • +
+

可直连骨干网:AS4134、AS4837、AS9929、AS58453

+

跟欧洲情况差不多。

+

电信163在美西较大程度上依赖Cogentco的互联,天天爆炸。

+
    +
  • Verizon
  • +
+

可直连骨干网:AS9929

+

联通9929与Verizon的互联一言难尽,延迟不是最优,单线程速度也不是最优。高峰期单线程速度在50-70Mbps震荡。而多线程速度倒是能跑满,非常的玄学。

+

有时候其他北美ISP到联通9929需要经Verizon转发,而被转发的速度就很难保证了。

+

需要注意的是,欧洲/北美的网络情况跟亚太差异比较大。欧美的中小ISP大部分依靠的是IX互联或者机房托管的混合网络接入。虽然商业网络的价格比亚洲地区便宜,但至少对中国用户来说,很少再回程路由中遇见欧美的Regional T1或者高质量T1 ISP。

+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/network-nginx/index.html b/public/network-nginx/index.html new file mode 100644 index 0000000..1bfee04 --- /dev/null +++ b/public/network-nginx/index.html @@ -0,0 +1,534 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

Network的艺术:Docker建站与反向代理

+ + + + + + +
+

前言 Docker的出现极大简化了建站流程,较过去的LAMP方式优雅了许多,配合Nginx反向代理可以快速上线HTTPS站点。

+

安装Docker

+

这里以Debian12为例:

+
    +
  • 官方安装脚本:
  • +
+
curl -fsSL https://get.docker.com -o get-docker.sh
+sudo sh get-docker.sh
+
+
    +
  • 使用 Docker 存储库安装
  • +
+

使用以下命令安装此方法的先决条件:

+
sudo apt update && sudo apt install ca-certificates curl gnupg
+
+

创建一个目录来存储密钥环:

+
sudo install -m 0755 -d /etc/apt/keyrings
+
+

使用给定的命令下载 GPG 密钥并将其存储在 /etc/apt/keyrings/etc/apt/keyrings 目录中:

+
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+
+

使用 chmod 命令更改 docker.gpg 文件的权限:

+
sudo chmod a+r /etc/apt/keyrings/docker.gpg
+
+

使用以下命令为 Docker 设置存储库:

+
echo \
+  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
+  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
+  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
+
+

现在可以使用以下命令更新存储库索引并安装 Docker:

+
sudo apt update && sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
+
+

使用Docker-Compose

+
    +
  • 目标:创建一个Searxng服务并对外开放。
  • +
  • 方法:创建两个 docker-compose 文件,并使用同一个外部 Docker 网络使两个服务互联。
  • +
+
    +
  1. 首先创建好工作目录,例如:
  2. +
+
.
+└── docker
+    ├── docker-compose.nginx.yml
+    ├── docker-compose.searxng.yml
+    └── nginx
+        ├── certs
+        │   ├── fullchain.pem
+        │   └── privkey.pem
+        └── searxng.conf
+
+
    +
  1. 在启动服务前,首先创建一个 Docker 外部网络(例如命名为 nginx):
  2. +
+
docker network create nginx 
+
+

这样,无论是哪个 docker-compose 项目中的容器,只要加入此网络,就能直接通信。

+
    +
  1. 编写 searxng 的 docker-compose 文件
  2. +
+
version: '3'
+
+services:
+  searxng:
+    image: searxng/searxng
+    container_name: searxng
+    restart: unless-stopped
+    ulimits:
+      nproc: 65535
+      nofile:
+        soft: 65535
+        hard: 65535   
+    volumes:
+      - /var/lib/docker/volumes/searxng/_data:/etc/searxng
+    networks:
+      - nginx
+    ports:
+      # 如果希望 searxng 只对内部服务开放,则可不映射外部端口
+      - "127.0.0.1:18080:8080"
+
+networks:
+  nginx:
+    external: true
+
+
    +
  1. 编写 Nginx 的 docker-compose 文件
  2. +
+

创建 nginx 的 docker-compose 文件,例如:

+
version: '3'
+
+services:
+  nginx:
+    image: nginx:latest
+    container_name: nginx
+    restart: unless-stopped
+    ports:
+      - "80:80"
+      # 如需要 HTTPS,请映射 443 端口并挂载证书目录
+      #- "443:443"
+    volumes:
+      - ./nginx/searxng.conf:/etc/nginx/conf.d/default.conf:ro
+      #- ./nginx/certs:/etc/nginx/certs:ro
+    networks:
+      - nginx
+
+networks:
+  nginx:
+    external: true
+
+
    +
  1. 编写 Nginx 配置文件
  2. +
+
server {
+    listen 80;
+    server_name searxng.dich.bid;
+
+    client_max_body_size 10M;
+
+    location / {
+        proxy_pass http://searxng:8080;
+        proxy_set_header Host $host;
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+        proxy_set_header X-Forwarded-Proto $scheme;
+        proxy_http_version 1.1;
+        proxy_set_header Connection "";
+    }
+
+    error_page 502 /502.html;
+    location = /502.html {
+        root /usr/share/nginx/html;
+        internal;
+    }
+}
+
+
    +
  1. 启动服务
  2. +
+
    +
  • 启动 searxng 服务:
  • +
+
docker-compose -f docker-compose.searxng.yml up -d
+
+
    +
  • 启动 nginx 服务:
  • +
+
docker-compose -f docker-compose.nginx.yml up -d
+
+

由于两者都加入了外部网络 nginx,nginx 内的proxy_pass http://searxng:8080就能解析到 searxng 容器,实现反向代理效果。现在,访问http://ip:18080就可以访问Searxng搜索引擎。

+

添加HTTPS

+

在实际生产环境中我们不能使用IP直接访问,因此需要为我们的站点开启SSL证书,也就是要申请证书并在配置文件中声明。

+
    +
  1. 证书生成
  2. +
+
    +
  • 如果只是用于测试可以生成自签名证书:
  • +
+
mkdir -p /home/dich/docker/nginx/certs
+openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
+  -keyout /home/dich/docker/nginx/certs/privkey.pem \
+  -out /home/dich/docker/nginx/certs/fullchain.pem \
+  -subj "/CN=your-domain.com"
+
+
    +
  1. 更改searxng.conf:
  2. +
+
server {
+    listen 443 ssl;
+    server_name searxng.dich.bid;
+
+    # SSL 证书配置
+    ssl_certificate /home/dich/docker/nginx/certs/fullchain.pem;
+    ssl_certificate_key /home/dich/docker/nginx/certs/privkey.pem;
+    ssl_protocols TLSv1.2 TLSv1.3;
+    ssl_ciphers HIGH:!aNULL:!MD5;
+
+    client_max_body_size 10M;
+
+    location / {
+        proxy_pass http://searxng:8080;
+        proxy_set_header Host $host;
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+        proxy_set_header X-Forwarded-Proto $scheme;
+        proxy_http_version 1.1;
+        proxy_set_header Connection "";
+    }
+
+    error_page 502 /502.html;
+    location = /502.html {
+        root /usr/share/nginx/html;
+        internal;
+    }
+}
+
+# HTTP 服务器块,将所有流量重定向到 HTTPS
+server {
+    listen 80;
+    server_name searxng.dich.bid;
+    return 301 https://$host$request_uri;
+}
+
+
    +
  1. 更改docker-compose.nginx.yml
  2. +
+
version: '3'
+
+services:
+  nginx:
+    image: nginx:latest
+    container_name: nginx
+    restart: unless-stopped
+    ports:
+      - "80:80"
+      # 如需要 HTTPS,请映射 443 端口并挂载证书目录
+      - "443:443"
+    volumes:
+      - ./nginx/searxng.conf:/etc/nginx/conf.d/default.conf:ro
+      - ./nginx/certs:/home/dich/docker/nginx/certs
+    networks:
+      - nginx
+
+networks:
+  nginx:
+    external: true
+
+
    +
  1. 启动新配置
  2. +
+
    +
  • 重启容器
  • +
+
sudo docker compose -f docker-compose.nginx.yml up -d
+
+
    +
  • 查看日志
  • +
+
sudo docker logs searxng
+
+

Caddy

+
+

Caddy 自 2015 年起用 Go 语言重写,定位为“开箱即用”的现代 Web 服务器,内置自动 Let’s Encrypt 证书管理和续期,默认支持 HTTP/2 及 HTTP/3(QUIC),并通过简洁明了的 Caddyfile 语法极大降低配置成本.

+
+
    +
  1. 示例结构:
  2. +
+
.
+└── compose
+    ├── certs
+    │   ├── cert.pem
+    │   └── key.pem
+    ├── compose.caddy.yml
+    ├── compose.miniflux.yml
+    ├── compose.searxng.yml
+    └── conf
+        └── Caddyfile
+
+
    +
  1. 同样创建名为Caddy的docker网络:
  2. +
+
docker network create caddy
+
+
    +
  1. 编写Caddy的compose,可以看到caddy可以自带签发证书:
  2. +
+
version: '3.7'
+
+# 自动签发模式
+
+services:
+  caddy:
+    image: caddy:latest
+    container_name: caddy
+    restart: unless-stopped
+    volumes:
+      - ./conf:/etc/caddy:ro 
+      - caddy_data:/data
+      - caddy_config:/config
+    ports:
+      - "80:80"    
+      - "443:443"  
+    networks:
+      - caddy     
+
+networks:
+  caddy:
+    external: true
+
+volumes:
+  caddy_data:
+  caddy_config:
+
+
+# 自备证书模式
+
+services:
+  caddy:
+    image: caddy:latest
+    container_name: caddy
+    restart: unless-stopped
+    environment:
+      - CADDYPATH=/etc/caddycerts    
+    volumes:
+      - ./conf:/etc/caddy
+      - ./certs:/etc/caddycerts   
+      - caddy_data:/data
+      - caddy_config:/config
+    ports:
+      - "80:80"
+      - "443:443"
+    networks:
+      - caddy
+
+volumes:
+  caddy_data:
+  caddy_config:
+networks:
+  caddy:
+    external: true
+
+
    +
  1. 编写Caddyfile,可以看到自动开启HTTPS模式:
  2. +
+
# 自动签发模式
+searxng.dich.bid {
+    reverse_proxy searxng:8080 {
+        header_up Host {upstream_hostport}
+    }
+}
+
+miniflux.dich.bid {
+    reverse_proxy miniflux:8080 {
+        header_up Host {upstream_hostport}
+    }
+}
+
+# 自备证书模式
+searxng.dich.bid {
+    reverse_proxy searxng:8080
+    tls /etc/caddycerts/cert.pem /etc/caddycerts/key.pem
+}
+miniflux.dich.bid {
+    reverse_proxy miniflux:8080
+    tls /etc/caddycerts/cert.pem /etc/caddycerts/key.pem
+}
+
+
    +
  1. Docker compose的用法不再赘述。
  2. +
+

FAQ

+
    +
  • 使用nginx的docker版本而非apt安装的版本;
  • +
  • 注意相对路径和绝对路径,不同容器可能冲突;
  • +
  • 使用网络创建的方法简化了配置;
  • +
  • 使用127.0.0.1:port的配置增加了安全性,无法ip访问;
  • +
  • conf中的服务端口是compose中的port:port的后一个;
  • +
  • 更改配置后需要删除现有的容器再生成;
  • +
  • version字段可以不需要;
  • +
  • 注意加上container_name;
  • +
  • 每增加一个服务需要在nginx中更新volume;
  • +
+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/network-ssl/index.html b/public/network-ssl/index.html new file mode 100644 index 0000000..8446170 --- /dev/null +++ b/public/network-ssl/index.html @@ -0,0 +1,257 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

Network的艺术:SSL/TLS证书

+ + + + + + +
+

前言 什么是SSL/TLS证书?它有什么作用?如何部署?

+

什么是SSL/TLS证书

+

SSL 的全称是 Secure Sockets Layer(安全套接字层),而 TLS 的全称是 Transport Layer Security(传输层安全协议)。最初由 Netscape 开发的 SSL 协议用于保护网络通信,但由于其存在的安全漏洞,后来被更新、更安全的 TLS 协议所取代。

+

如今,当我们谈论“SSL 证书”时,实际上指的是支持 TLS 协议的数字证书,两者在功能上没有本质区别,只是在命名上沿用了历史传统。该证书是由受信任的数字证书颁发机构 CA,在验证服务器身份后颁发,且具有服务器身份验证和数据传输加密功能。简单来说就是HTTP+SSL/TLS证书=HTTPS.

+

SSL证书是如何工作的

+
    +
  • 当我们点击一个超链接(HTTP),浏览器帮我们跳转到新标签页;
  • +
  • 通过DNS(Domain name system)查询找到该域名(地址栏中的如www.xxx.com之类的字符)对应的IP地址,可能是某个CDN的地址;
  • +
  • 服务器上已经配置好certificate.crt(公钥)和private.key(私钥);
  • +
  • CDN随后与真正的服务器建立连接,服务器上的反向代理(可能是nginx或者caddy)检测连接,并用配置好的证书将连接升级为HTTPS;
  • +
  • HTTPS握手并将内容显示在浏览器上。
  • +
+

SSL/TLS证书的握手过程

+
    +
  • 客户端发送"ClientHello"消息,包含支持的加密算法和TLS版本;
  • +
  • 服务器回应"ServerHello"消息,选择加密算法并发送SSL/TLS证书;
  • +
  • 客户端验证证书的有效性(通过内置的CA根证书);
  • +
  • 客户端使用服务器公钥加密一个"预主密钥"并发送给服务器;
  • +
  • 双方根据预主密钥生成会话密钥;
  • +
  • 使用会话密钥进行加密通信;
  • +
  • 加密通信:握手完成后,所有数据传输都使用协商好的对称密钥加密。
  • +
+
+

使用公钥加密的数据只能用对应的私钥解密,使用私钥加密(签名)的数据可以用对应的公钥验证。

+
+
+

客户端和服务器都支持非常多的密码套件,比如“ECDHE-RSA-AES256-GCM-SHA384”。格式是“密钥交换算法 + 签名算法 + 对称加密算法 + 摘要算法”,这个密码套件的意思就是:“握手时使用 ECDHE 算法进行密钥交换,用 RSA 签名和身份认证,握手后的通信使用 AES 对称算法,密钥长度 256 位,分组模式是 GCM,摘要算法 SHA384 用于消息认证和产生随机数。”

+
+

CA证书

+

可以看到,验证证书的有效性需要通过CA证书,由CA机构(如DigiCert +Let's Encrypt)等颁布,CA证书的层级结构如下:

+
    +
  • 根CA证书:最高级别的证书,自签名,是整个信任链的起点.
  • +
  • 中间CA证书:由根CA签发,可以签发终端实体证书或其他中间CA证书.
  • +
  • 终端实体证书:由根CA或中间CA签发给网站、服务器等实体使用.
  • +
+

操作系统和浏览器内置了受信任的根CA证书列表,当验证网站证书时,系统会沿着证书链向上追溯至根CA;如果能找到一个受信任的根CA,且证书链上所有签名有效,则验证通过.这就是保护我们上网安全的信任链的基础。

+

当我们访问网页时,往往会看到左上角的图标,里面是Google Trust Services或者DigiCert Inc等等,代表证书的颁发来源。如果锁提示不安全,可能是证书过期或者找不到CA证书,即有可能是自签名证书。什么是自签名证书?

+

证书颁发

+

我们先来看证书颁发的流程。

+
    +
  • 证书申请:网站所有者向证书颁发机构(CA)申请SSL/TLS证书,提供域名和组织信息。
  • +
  • 身份验证:CA验证申请者的身份和域名所有权。验证方式包括域名验证(DV)、组织验证(OV)或扩展验证(EV)。
  • +
  • 证书签发:验证通过后,CA使用其私钥为申请者签发数字证书,包含公钥、域名信息、颁发者信息和有效期等。
  • +
  • 安装部署:网站管理员将证书安装到Web服务器上。
  • +
+

可以看到过程有点麻烦,个人建站的话往往使用自签名证书,即ssh-keygen生成的公钥和私钥,由于没有CA所以会显示不安全。

+

申请证书

+
    +
  • +

    sslforfree由 ZeroSSL 支持颁发的免费SSL证书.

    +
  • +
  • +

    通过AMH提供的自助在线申请服务申请SSL通配符证书.需要注册AMH账号.

    +
  • +
  • +

    letsencrypt,支持申请多渠道SSL证书.

    +
  • +
  • +

    借助Punchsalad提供的在线服务申请SSL证书,无需登录,仅需邮箱即可完成SSL通配符证书申请和签发.

    +
  • +
+

DV/OV/EV SSL证书的区别

+

以下是三种主要SSL证书验证类型的对比:

+ + + + + + + + + + + +
特性域名型SSL (DV SSL)企业型SSL (OV SSL)增强型SSL (EV SSL)
验证级别最低中等最高
验证内容仅验证域名所有权验证域名所有权和组织信息最严格的验证,包括法律、物理和运营存在的全面验证
验证流程自动化验证(邮件、DNS记录等)半自动验证人工审核为主
签发时间几分钟到数小时1-3个工作日5-7个工作日
浏览器显示普通锁图标普通锁图标地址栏绿色显示(部分浏览器已取消)
适用场景个人博客、信息网站企业网站、电子商务银行、金融机构、大型电商
成本中等
信任度基本中等最高
证书信息只包含域名信息包含组织名称和域名包含完整的组织详细信息
安全加密强度相同相同相同
+

证书类型

+

有时候可以购买如*.xxx.com的通配符证书,即一个证书通用与所有子域名。以及还有其他如多域名证书和上面提到的DV/OV/EV证书的类型。

+ + + + + +
证书类型覆盖范围安全级别验证过程适用场景价格范围
单域名证书仅一个特定域名基本到高DV/OV/EV个人网站或小型企业低到高
通配符证书主域名及其所有一级子域名基本到中等DV/OV拥有多个子域名的网站中等到高
多域名证书(SAN)多个不同域名基本到高DV/OV/EV管理多个不相关域名的企业中等到高
自签名证书任意无需验证测试环境、内部网络免费
+
+

Done.

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/network-zuwang/index.html b/public/network-zuwang/index.html new file mode 100644 index 0000000..717ad25 --- /dev/null +++ b/public/network-zuwang/index.html @@ -0,0 +1,329 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+ +

Network的艺术:家庭组网方案与设备选购

+ + + + + + +
+

前言 本文介绍一些家庭组网方案和家庭网络升级方案。

+

零.预备知识

+
    +
  • AC:网络控制器,一般为闭源的成熟方案;起到路由和管理的功能。
  • +
  • AP:Wi-Fi发射器,一般不起路由功能,对性能要求不高。
  • +
  • PPPoE拨号:输入用户名、密码认证成功后即可点对点拨号上网
  • +
  • 桥接:让光猫只起到光电转换作用,路由工作交给下一级设备。
  • +
  • Mesh:一种网络拓扑结构,可以实现节点之间的多跳通信,使其覆盖范围和信号质量大幅提高
  • +
  • FTTH:Fiber to the Home,小区光纤箱到你家然后下级连网线。
  • +
  • FTTR:Fiber to The Room,光纤到你家然后下级也连光纤。
  • +
  • 软路由:即为X86设备或Arm设备的小主机刷Openwrt或其他路由系统,一般没有Wi-Fi功能,具有两个以上的RJ45网口,性能较强;
  • +
  • 硬路由:即为常见的带有天线的路由器,带有Wi-Fi,一般为arm或mips设备,搭载板载内存,性能较弱
  • +
+

一.电组网(网线)方案

+

AC+AP

+
    +
  • 1.弱电箱光猫+箱内AC+各个房间网线直连AP
  • +
+
企业级方案,美观漫游信号好,成本稍高,比较省心;
+
+
    +
  • 2.弱电箱光猫+软路由AC+各个硬路由刷AP
  • +
+
同上,自定义程度高,适用与有一定技术基础的用户,性价比高;
+一般可以使用集客AC/AP系统。
+
+
    +
  • 3.弱电箱光猫(光电转换)+软路由(PPPoE+DHCP)+AC
  • +
+
即为光猫改桥接,软路由PPPoe拨号;这样增加了一层设备,需要谨慎考虑。
+
+
    +
  • 4.SFP猫棒(光模块)+2.5G网管型交换机/AC+AP
  • +
+
光猫一般有Wifi+PPPoE+IPTV+光纤固话功能,如果不想用光猫可以替代为此方案;
+IPTV设置Vlan解决,固定电话设置为转发到个人手机号或取消.
+
+

Mesh

+
    +
  • 5.弱电箱光猫+网线直连硬路由+无线Mesh连接到另一台同型号路由器
  • +
+
适用与家里预埋的网口不多的情况,无线Mesh需要AX3000及以上同型号路由器;
+也可以将硬路由刷机用Easymesh实现。
+
+
    +
  • 6.弱电箱光猫+网线直连硬路由+有线连接到另一台同型号路由器
  • +
+
适用与有足够的预埋网口,比无线Mesh稳定。
+如果两台路由器之间不能直接连接,则需要有线回程,
+即为弱电箱光猫+有线连接到路由器+连回弱电箱交换机+有线连接到另一台路由器.
+
+
    +
  • 7.弱电箱光猫+电力猫+220V电线+电力猫
  • +
+
比较小众的组网方案,使用电线传输数据,速度不高,容易受到大功率电器的干扰,
+适用与没有预留网口/布线不方便的环境;
+
+

混合方案

+
    +
  • 8.弱电箱光猫+软路由(主路由)+两台路由器(AP模式)互相Mesh
  • +
+
+

单层楼环境优先考虑Mesh组网,多层楼环境优先考虑AC+AP;

+
+
+

如果要实现全屋2.5G网络,可以直接更换2.5G光猫+带2.5G口下接设备,注意需要宽带套餐/光猫/路由器/网线/终端设备全部支持2.5G才能跑到近似网速;

+
+
+

如果需要2.5G以上更高带宽,则考虑光组网方案,也可以像方案4买相应性能的交换机设备;

+
+
+

不建议使用光猫自带的wifi,光猫同时PPPoE拨号+DHCP路由+发射wifi,性能不够会造成大量发热。

+
+

二.光组网(光纤)方案

+

光纤方案性能强大,但光纤便宜而光电转换设备贵,而且最终还是要连到RJ45网口或无线,中间需要光转电转换器,性能要打个问号;且后期维护成本高,需谨慎考虑。

+
    +
  • 8.FTTR:OLT+FTTR光猫(AC)+分光器和单模/多模光纤+多个从光路由(AP)
  • +
+
光AC+AP,性能强大,但比较昂贵,自定义程度小;
+
+
    +
  • 9.FTTR:OLT+FTTR光猫(主)+分光器和单模/多模光纤+从光路由(副)
  • +
+
主副光猫Mesh,性质同上;
+光纤需要考虑光衰,且没有网线耐用,打头工具也比网线贵的多,而且需要注意合约内容;
+当然,也可以在装修阶段就部署光电复合缆,会有更多的选择空间。
+
+

三.路由器工作原理

+

路由器是计算机网络中的重要设备,主要用于连接不同的网络,并在这些网络之间转发数据。其工作原理涉及以下几个主要方面:

+
    +
  • +

    1.数据包转发:路由器根据目标地址将数据包从一个网络转发到另一个网络。它通过查找路由表来确定最佳路径,并将数据包转发到正确的输出端口。

    +
  • +
  • +

    2.路由表:路由器维护一个路由表,其中包含了网络的拓扑结构以及到达每个网络的最佳路径信息。路由表可以通过静态配置或动态路由协议(如OSPF、BGP等)自动学习和更新。

    +
  • +
  • +

    3.数据包处理:当路由器接收到数据包时,它会检查数据包的目标IP地址,并根据路由表确定应该转发到哪个端口。路由器还可能执行其他功能,如网络地址转换(NAT)、质量服务(QoS)和防火墙等。

    +
  • +
  • +

    4.连接多个网络:路由器通常具有多个网络接口,可以连接不同的网络。这些网络接口可以是以太网、Wi-Fi、光纤等,使路由器能够在不同类型的网络之间进行数据转发。

    +
  • +
  • +

    5.路由器协议:路由器使用不同的协议来实现数据包转发和路由表的更新。这些协议包括IP协议用于数据包交换,动态路由协议用于路由表的学习和更新,以及其他协议用于网络管理和安全。

    +
  • +
+

一般而言,家用路由器使用 DHCP 模式,由上级网关的网线连接到路由器的WAN口,如小米路由器的192.168.31.1,在浏览器输入此地址可以进入管理界面,并可以发现了解连接该无线网络的设备地址都为192168.31.xx;且路由器的几个Lan口可以做交换机使用。

+

四.路由器的选择与常见误区

+

路由器的信号好不好,一般而言,与以下几点相关:

+

1.路由器支持的协议类型:

+

路由器命名常见的格式为AX3000、AC1800等,前面代表协议,后面数字表示速率(Mbps);AX(802.11ax)在相同速率下比AC更快,即Wifi6比Wifi5要好。在相同协议下,一般速率越高越好;千兆优于百兆,但需注意千兆端口和千兆天线的产品。

+
    +
  • +

    速度:Wi-Fi 6 比 Wi-Fi 5 更快。Wi-Fi 5 支持的最高速度为1.3 Gbps(理论上),而 Wi-Fi 6 的最高速度为9.6 Gbps(同样是理论上的速度)。这意味着Wi-Fi 6可以提供更快的数据传输速率,特别是在拥挤的网络环境中。

    +
  • +
  • +

    容量:Wi-Fi 6比 Wi-Fi 5具有更好的网络容量管理。Wi-Fi 6采用了一些技术,如 OFDMA(正交频分复用多址)和 MU-MIMO(多用户多输入多输出),使得网络更有效地管理多个设备的连接。这意味着 Wi-Fi 6在拥挤的网络环境中能够更好地处理大量设备的连接,而不会出现性能下降。

    +
  • +
  • +

    延迟与功耗:Wi-Fi 6 比 Wi-Fi 5 具有更低的延迟。通过一些新的技术,如目标唤醒时间(TWT)和 BSS 领导者切换,Wi-Fi 6 能够在连接设备之间实现更快的响应时间和更低的延迟,也可以更有效地管理设备的电量消耗,延长设备的电池寿命。这对于需要快速响应的应用,如在线游戏和视频会议,尤其重要。

    +
  • +
+

在 Wifi6 普及的当下,建议购买 WiFi6 路由器,并且此类路由器往往还带有 wifi5 备用网络,可与老旧设备兼容,不必担心。小心百兆网口和千兆天线的牛马产品

+
+

目前Wifi7设备逐渐推出,但在中国大陆地区大部分频段被划分给5G使用,Wifi7实际的提升微乎其微。

+
+

2.路由器支持的速率:

+

不要盲目追求大数字:路由器标注的无线速率是叠加速率,并非单一设备接入的最大速率。例如,标注为1750Mbps的路由器,实际上是由2.4GHz的450Mbps和5GHz的1300Mbps相加而成,单一设备的最大通信速率只有1300Mbps。大多数家庭接入的光纤速率为千兆(1000Mbps),因此最大速度为125MB/s,因此瓶颈通常不在于路由器性能;选购家用路由器,更重要的是提高信号覆盖面积和强度,能跑满千兆已经不错。

+

3.路由器的无线频段:

+

2.4GHz频段稳定性高,覆盖范围广,穿墙能力强;而5GHz频段速度快但穿墙能力较弱

+

4.无线网络的频段带宽:

+

2.4G有20Mhz和40Mhz两种频道带宽,5G则有80Mhz和160Mhz两种;频道带宽就是发射频率的宽度,带宽越低穿透性越好。如果连的设备多的话,就用低频段;

+

5.芯片的主频和板载内存

+

路由器处理器的主频越高,加解密性能越好,速度和带机量也更大;目前低价位路由器通常使用MTK、瑞昱、海思等廉价处理器,配以64MB/128MB的内存。而高端路由器多使用博通的高端芯片,在内存的配置上往往可以达到256MB以上。博通高端芯片在各个方面表现都不错,同时各位大神对刷机的支持力度也比较大。板载内存越大可为后续刷机留下空间,并支持插件等;

+

6.其他功能

+

如 QOS,设备管理,IPTV 支持,IPV6 等等;

+
+

天线越多信号不一定越强。

+
+

路由器的发射范围是由协议决定的,与根数无关。对于双频的路由来说,4根或者6根其实只有一半(2根2.4g和2根5g使用)。

+
+

无线功率不是越大越好。

+
+

因为无线通信是双向的,路由器功率大了,但是你的手机等无线终端设备功率是不变的。在符合国家标准的情况下,wifi 功率是有硬性标准的,单台路由器覆盖80平以上的面积不太现实。因此当你面对信号差、覆盖死角的时候,应该首要想到的是增加覆盖节点,而不要相信宣传所谓的“穿墙王”

+

五.网线的选择与布线

+

1. 网线选择建议:

+

在考虑网络建设方面,从经济效益角度而言,超五类网线已经足以满足大多数家庭的千兆网络需求(1Gbps)。在短距离内,质量较高的五类/超五类网线支持高达2500兆的传输速率(2.5Gbps)。因此,一般情况下,考虑到成本因素,建议家庭网络布线选用符合标准的超五类网线。

+

若愿意适度增加布线成本,则推荐选择支持万兆(10Gbps)网络的六类/超六类以上网线,尤其是从光猫到主路由/交换机的这一段线路,最好支持万兆。即便今后需要扩展网络速度无法满足万兆的有线条件,也可以通过 Wi-Fi7 标准实现无线超万兆速度覆盖。

+

2. 网线布线注意事项:

+

在进行网线布线时,无论是屏蔽网线还是非屏蔽网线,都应确保将强电线和弱电线分开放置于不同的管道中。同时,在走线过程中应保持一定的间距,以减少干扰。若需要考虑未来更换网线的情况,建议选择更大的穿线管道,并确保每条网线单独走一根管道。若出现强、弱电交叉走线的情况,可采用铝/锡纸包裹弱电管道以实现简单的屏蔽作用。应避免与大功率强电线相交或并行走线,如空调、烤火炉、微波炉等。

+

3. 弱电箱至电视柜网线布线:

+

考虑到当前电信运营商提供的IPTV功能,如果不熟悉设置VLAN的单线复用,或者未来可能使用到链中聚合技术,建议从弱电箱至电视柜至少布置两条网线,以免后悔。

+

4. 接线盒的预留:

+

许多人可能认为随着21世纪的到来,有线布线已经过时。因此,为了节约成本或受装修公司的误导,一些卧室甚至书房都没有进行网线布置,这是不可取的。无线网络虽然方便,但速度远不如有线快速稳定。因此,建议在每个卧室的相应位置安装一个网线接线盒,并在墙壁上安装电视时,下方也应预留一个网线接线盒。如果有地下室或楼阁,也应该布置一条网线。多预留一些接线盒总比今后发现需要网线却没有的尴尬情况要好。

+

5. 死角位置的网线和电源接口预留:

+

对于信号死角的位置,根据实际情况,如阳台、露台等不需要路由器设备可见的地方,可以考虑将路由器隐藏在吊顶中,甚至包括厕所的吊顶也可以考虑。在这些位置预留多个网线和电源接口是明智的选择。

+

6. 路由器放置位置推荐:

+

一般来说,家庭会将路由器放置在弱电箱或电视柜内,然而,周围其他电器设备运行时会产生电磁干扰,对2.4G和5G信号都会造成影响,甚至蓝牙设备也会有干扰。基于信号向下传播的特性,建议将路由器放置在较高位置,如吊顶内或进门处的高处,并最好选择居住区域的中心位置以实现更好的信号覆盖。

+ +
+ + + + +
+ +
+ + + + +
+ + + diff --git a/public/page/1/index.html b/public/page/1/index.html new file mode 100644 index 0000000..6d79d92 --- /dev/null +++ b/public/page/1/index.html @@ -0,0 +1,6 @@ + + + + +Redirect +

Click here to be redirected.

diff --git a/public/page/10/index.html b/public/page/10/index.html new file mode 100644 index 0000000..b2d3171 --- /dev/null +++ b/public/page/10/index.html @@ -0,0 +1,308 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+
+ +

Linux之旅(七):系统与终端字体设置

+ + + + + + + + +
+

前言 一个好看的字体会提高工作效率与审美.Linux 下的字体可以很漂亮,但需要一些设置.

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

Linux之旅(六):常用命令与性能分析

+ + + + + + + + +
+

前言 在学习Linux操作系统时,熟悉常用命令和性能分析工具是至关重要的。让我们一起探索Linux的世界,提升技能,解锁无限可能!

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

Linux之旅(五):BIOS-UEFI-MBR-GPT-GRUB

+ + + + + + + + +
+

前言 在计算机领域,系统引导和磁盘分区是至关重要的。本文将介绍BIOS与UEFI,MBR与GPT,以及它们之间的异同点。此外,我们还会讨论与这些概念密切相关的引导加载程序——GRUB。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

Linux之旅(四):Terminal,Console and Shell

+ + + + + + + + +
+

前言 在linux的学习过程中,我们常常遇到诸如 Terminal,Console,bash,zsh,shell,tty 等概念,这些概念常常被混淆,似乎都和命令行相关。本文从历史角度出发介绍它们的前世今生。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

Linux之旅(三):内核/shell/包管理/文件系统/桌面环境

+ + + + + + + + +
+

前言 在Linux世界中,内核/shell/包管理/文件系统构成了Linux系统的核心,它们相互配合,共同构建了一个强大而稳定的操作环境。本文将深入探讨这些关键组成部分,解释它们的作用和原理,帮助读者更好地理解Linux系统的运作机制。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +
+ + + + +
+ + + diff --git a/public/page/11/index.html b/public/page/11/index.html new file mode 100644 index 0000000..b093cb1 --- /dev/null +++ b/public/page/11/index.html @@ -0,0 +1,202 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+
+ +

Linux之旅(二):FHS与目录结构

+ + + + + + + + +
+

前言 在Linux世界中,Filesystem Hierarchy Standard(FHS)是一座引导我们进入系统核心的桥梁,它定义了Linux系统中目录结构的规范与作用,为我们提供了一张清晰的地图,指引我们轻松管理和理解系统。本文将深入探讨FHS规范与Linux系统目录结构,解释各个目录的用途与功能,帮助我们更好地理解和利用Linux系统。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

Linux之旅(一):构成与发行版

+ + + + + + + + +
+

前言 Linux 作为一款强大、灵活且免费的操作系统,吸引了越来越多的用户。然而,对于初学者来说,Linux 可能显得有些陌生,甚至有些令人望而生畏。本文旨在为那些刚踏入 Linux 世界的新手提供一份指南,帮助他们更好地了解、使用这个令人着迷的操作系统。我们将探讨Linux的基本概念,解释为何选择Linux,深入剖析其主要构成要素以及不同的发行版之间的差异。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +
+ + + + +
+ + + diff --git a/public/page/2/index.html b/public/page/2/index.html new file mode 100644 index 0000000..fedb64e --- /dev/null +++ b/public/page/2/index.html @@ -0,0 +1,308 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+
+ +

乱七八糟:GFS项目考量笔记

+ + + + + + + + +
+

前言 最近nekoray项目归档,考量新的singbox前端时发现这个项目不错,不过在Arch linux中运行有一些小问题,这里做个总结。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:FRP使用指南

+ + + + + + + + +
+

前言 FRP (Fast Reverse Proxy) 是一个用Go语言开发的高性能反向代理应用,可以帮助您轻松地进行内网穿透,对外提供服务.

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:Ventoy战斗盘部署

+ + + + + + + + +
+

前言 ​Ventoy 是一款开源免费的多系统启动盘制作工具,这里说明其主要功能的制作流程。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

Network的艺术:家庭组网方案与设备选购

+ + + + + + + + +
+

前言 本文介绍一些家庭组网方案和家庭网络升级方案。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:2024年度总结

+ + + + + + + + +
+

前言 又是新的一年,时间流速感觉越来越快了。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +
+ + + + +
+ + + diff --git a/public/page/3/index.html b/public/page/3/index.html new file mode 100644 index 0000000..f415bcc --- /dev/null +++ b/public/page/3/index.html @@ -0,0 +1,308 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+
+ +

乱七八糟:Vim编辑器速查

+ + + + + + + + +
+

前言 Vim 是从早期的 vi 编辑器发展而来的增强版,其名称代表“Vi IMproved”。由荷兰程序员 Bram Moolenaar 于 1991 年首次发布。Vim 是开源软件,支持多种操作系统,包括 Unix、Linux、Windows 和 macOS 等。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

Network的艺术:Docker建站与反向代理

+ + + + + + + + +
+

前言 Docker的出现极大简化了建站流程,较过去的LAMP方式优雅了许多,配合Nginx反向代理可以快速上线HTTPS站点。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:服务器初始化与安全设置

+ + + + + + + + +
+

前言 本文记录服务器常用操作步骤。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:跑步笔记(二)

+ + + + + + + + +
+

前言 最近读得<<亮哥跑经>>一书,遂迷上跑步;奈何体重偏高,略微有些吃力.以下是一些笔记:

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:跑步笔记(一)

+ + + + + + + + +
+

前言 最近读得<<亮哥跑经>>一书,遂迷上跑步;奈何体重偏高,略微有些吃力.以下是一些笔记:

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +
+ + + + +
+ + + diff --git a/public/page/4/index.html b/public/page/4/index.html new file mode 100644 index 0000000..071525c --- /dev/null +++ b/public/page/4/index.html @@ -0,0 +1,312 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+
+ +

乱七八糟:计算机科学优质视频

+ + + + + + + + +
+

前言 CSdiy珠玉在前,为CS教育做出了极大贡献.这里分享一些优质的CS学习相关视频.

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:Windows-Jupyter开发Python

+ + + + + + + + +
+

前言 由于 Windows 中开发环境较 linux 复杂,这里总结 Windows 中使用 Jupyter 开发 Python 的环境配置。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:Windows-VScode开发C/C++

+ + + + + + + + +
+

前言 由于 Windows 中开发环境较 linux 复杂,这里总结 Windows 中使用 VScode 开发 C/C++ 的环境配置。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:Windows封装与全自动安装

+ + + + + + + + +
+

前言 由于厂商默认安装windows家庭版导致各种问题频发,这里作者封装了一个开箱即用的,全自动安装,激活和优化的Windows11镜像。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:Windows安装与环境配置

+ + + + + + + + +
+

前言 由于厂商默认安装windows家庭版导致各种问题频发,这里对 widnows 安装做一个总结,以及附上我个人的windows配置。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +
+ + + + +
+ + + diff --git a/public/page/5/index.html b/public/page/5/index.html new file mode 100644 index 0000000..14ac8d0 --- /dev/null +++ b/public/page/5/index.html @@ -0,0 +1,310 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+
+ +

乱七八糟:Windows激活那些事

+ + + + + + + + +
+

前言 Windows的正版售价十分昂贵,2025年的今天大部分人都使用着OEM厂商自带的windows系统或自己想办法激活,那么,激活到底是什么原理?

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:Windows常用操作

+ + + + + + + + +
+

前言 Windows操作系统作为全球最为普及的桌面操作系统之一,其用户界面的设计非常经典,但存在许多不足之处,本篇记录一些常用脚本。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:常用实用快捷键

+ + + + + + + + +
+

前言 在日常使用浏览器时,掌握一些快捷键和技巧可以节省大量时间,提高工作和学习效率。通过学习和实践,能够更加轻松地应对各种网页浏览场景,让浏览器成为工作和学习的得力助手。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

搭建个人信息流:播客收听指北

+ + + + + + + + +
+

前言 讲起播客,许多人第一反应是喜马拉雅,但其实播客的订阅和收听有许多种方式。本文带你了解订阅播客的各种方式,并告诉你市面上有哪些不错的播客客户端可供选择。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

搭建个人信息流:RSS阅读指南

+ + + + + + + + +
+

前言 RSS 提供了一种数据格式,以 XML(可扩展标记语言)的形式组织信息,包括文章标题、摘要、链接和发布日期等。这些信息形成了所谓的“订阅源”(Feed),用户可以使用RSS阅读器(Feed Reader)来订阅这些源。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +
+ + + + +
+ + + diff --git a/public/page/6/index.html b/public/page/6/index.html new file mode 100644 index 0000000..98b503c --- /dev/null +++ b/public/page/6/index.html @@ -0,0 +1,308 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+
+ +

乱七八糟:开源软件与协议

+ + + + + + + + +
+

前言 本文旨在介绍开源以及开源许可证,这些许可证规定了使用、修改和分发开源软件的条件。通过了解不同类型的开源许可证及其特点,读者将能够更好地理解在开发和使用开源软件时的法律和道德责任。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

电子邮件是如何工作的:自建域名邮箱

+ + + + + + + + +
+

前言 poste.io 邮件服务基于 Docker 搭建,用的是 Haraka + Dovecot + SQLite 邮件系统,占用资源较少,安装简单,适合个人使用。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

电子邮件是如何工作的:POP3/IMAP/SMTP

+ + + + + + + + +
+

前言 POP3、IMAP 和 SMTP 是用于电子邮件传输的常见协议和服务,这些协议共同构成了电子邮件系统的基础,允许用户接收、发送和管理电子邮件。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

电子邮件是如何工作的:SPF/DKIM/DMARC

+ + + + + + + + +
+

前言 在互联网的日常使用中,电子邮件作为一项基础服务扮演着重要的角色。尽管在过去几十年里出现了各种新型的通讯方式,但电子邮件仍然保持着其不可替代的地位。了解电子邮件的工作原理,有助于更好地理解这一基础服务是如何运作的。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

Network的艺术:CDN技术与应用

+ + + + + + + + +
+

前言 内容分发网络(CDN)是一组分布在不同地理位置的服务器网络,使用户能够就近获取内容,从而降低延迟并缓解源站压力​.

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +
+ + + + +
+ + + diff --git a/public/page/7/index.html b/public/page/7/index.html new file mode 100644 index 0000000..9b74f99 --- /dev/null +++ b/public/page/7/index.html @@ -0,0 +1,308 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+
+ +

Network的艺术:SSL/TLS证书

+ + + + + + + + +
+

前言 什么是SSL/TLS证书?它有什么作用?如何部署?

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

Network的艺术:国内至国际骨干ISP线路整理

+ + + + + + + + +
+

前言 本文主要探讨的是IPv4网络,国际出口线路的质量分析以及各大ISP的介绍。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

Network的艺术:下载技术的历史

+ + + + + + + + +
+

前言 下载,就是将我们所需要的文件数据,通过网络从拥有该文件资源的计算机上传输过来并保存到我们的计算机上,供我们使用。本系列将详细讲述各种常见网络下载技术的原理,包括HTTP,FTP,BT等等。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:Git使用简明手册

+ + + + + + + + +
+

前言 Git,作为现代软件开发中不可或缺的版本控制工具,常常让初学者感到困惑。本文旨在介绍 Git 的全流程安装和基本使用,希望能够帮助新手更轻松地理解和掌握 Git 的基本概念和操作。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:垃圾清理的艺术

+ + + + + + + + +
+

前言 在从前的机械硬盘时代,由于硬盘空间小,且没有时常清理垃圾文件,常常导致硬盘空间严重不足;特别是在以 Windows 平台为代表的 C/D盘 体系下。那么,我们常说的垃圾清理,释放硬盘空间,到底是在清理什么?哪些文件可以被清理?

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +
+ + + + +
+ + + diff --git a/public/page/8/index.html b/public/page/8/index.html new file mode 100644 index 0000000..341e052 --- /dev/null +++ b/public/page/8/index.html @@ -0,0 +1,308 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+
+ +

乱七八糟:个人博客搭建

+ + + + + + + + +
+

前言 个人博客的搭建具有许多的方案可以选择,本文介绍如何快速部署一个博客,并将其发布到公网。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:机械革命键盘失灵拯救记

+ + + + + + + + +
+

前言 机械革命作为一款极高性价比的笔记本,其优惠的力度和问题不断的故障让玩家们爱恨交织;作者在其上安装 Linux 时遇到了键盘失灵的问题,为了避免更多人踩坑,故写本文。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:常见发音错误术语集合

+ + + + + + + + +
+

前言 中文和英语发音习惯不同,容易引起误解。本文旨在帮助您准确发音常见的科技术语,欢迎随时补充。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

乱七八糟:流量卡购买与套路

+ + + + + + + + +
+

前言 由于临近升学,校园网不尽人意,因此许多小伙伴有了买一张流量卡的计划。本文以三大运营商为例,说明常见流量卡的套路与选择。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

综合工程:Arch-linux 安装与配置

+ + + + + + + + +
+

前言 Arch linux是一个轻量、灵活、滚动更新的 Linux 发行版,衍生了诸多优秀的桌面端linux。其官方Wiki更是被称为技术界的“武林秘籍”;这里介绍其安装与使用。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +
+ + + + +
+ + + diff --git a/public/page/9/index.html b/public/page/9/index.html new file mode 100644 index 0000000..cd680d0 --- /dev/null +++ b/public/page/9/index.html @@ -0,0 +1,308 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + +
+ +
+
+ +

综合工程:Android-TV 折腾小记

+ + + + + + + + +
+

前言 由于 AppleTV 的高昂的售价和普通电视盒子广告的泛滥,一台开源、多功能的原生安卓电视盒子逐渐成为智能家居的必备神器。出于对 IPTV、YouTube 和家庭影院等需求,以及对一面赏心悦目电视墙的期待,这里分享 Android TV (以下简称ATV)安装的一些要点。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

综合工程:安卓刷机与root教程

+ + + + + + + + +
+

前言 自安卓系统诞生以来,root 一直是玩机的必备过程。时至今日,在安卓定制系统日益完善的情况下,能 root 的机型越来越少,本文以小米手机为例,介绍 root 的具体方法。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

综合工程:OpenWrt路由部署与软件编译

+ + + + + + + + +
+

前言 openwrt 是一个自由的、兼容性好的嵌入式 linux 发行版。作为软路由玩家必备的一款神器,可以实现诸如去广告,多拨和科学上网等多种功能。本文介绍openwrt在各种平台上的部署流程。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

综合工程:PVE安装与MC服务器搭建

+ + + + + + + + +
+

前言 假期将至,不少家里有闲置设备的小伙伴想尝试开设一个我的世界(Minecraft)服务器,却不知从何下手。本文以 PVE-Debian-MCSM 为主线介绍其部署流程。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +

综合工程:linux搭建安卓虚拟机

+ + + + + + + + +
+

前言 linux搭建安卓虚拟机有Waydroid,QEMU和Docker三种方案,各有不同。

+
+
+ + + Read more  + ↩︎ + +
+ + +
+ +
+ +
+ + + + +
+ + + diff --git a/public/pagefind/fragment/en_0285eb3.pf_fragment b/public/pagefind/fragment/en_0285eb3.pf_fragment new file mode 100644 index 0000000..a2d9fd1 Binary files /dev/null and b/public/pagefind/fragment/en_0285eb3.pf_fragment differ diff --git a/public/pagefind/fragment/en_11558d4.pf_fragment b/public/pagefind/fragment/en_11558d4.pf_fragment new file mode 100644 index 0000000..29e64c9 Binary files /dev/null and b/public/pagefind/fragment/en_11558d4.pf_fragment differ diff --git a/public/pagefind/fragment/en_147b5dd.pf_fragment b/public/pagefind/fragment/en_147b5dd.pf_fragment new file mode 100644 index 0000000..5d7b0ec Binary files /dev/null and b/public/pagefind/fragment/en_147b5dd.pf_fragment differ diff --git a/public/pagefind/fragment/en_149bd3d.pf_fragment b/public/pagefind/fragment/en_149bd3d.pf_fragment new file mode 100644 index 0000000..0a940fa Binary files /dev/null and b/public/pagefind/fragment/en_149bd3d.pf_fragment differ diff --git a/public/pagefind/fragment/en_14ff694.pf_fragment b/public/pagefind/fragment/en_14ff694.pf_fragment new file mode 100644 index 0000000..28d6485 Binary files /dev/null and b/public/pagefind/fragment/en_14ff694.pf_fragment differ diff --git a/public/pagefind/fragment/en_15721d4.pf_fragment b/public/pagefind/fragment/en_15721d4.pf_fragment new file mode 100644 index 0000000..006e380 Binary files /dev/null and b/public/pagefind/fragment/en_15721d4.pf_fragment differ diff --git a/public/pagefind/fragment/en_1aaf994.pf_fragment b/public/pagefind/fragment/en_1aaf994.pf_fragment new file mode 100644 index 0000000..1477395 Binary files /dev/null and b/public/pagefind/fragment/en_1aaf994.pf_fragment differ diff --git a/public/pagefind/fragment/en_1b3734f.pf_fragment b/public/pagefind/fragment/en_1b3734f.pf_fragment new file mode 100644 index 0000000..400ca04 Binary files /dev/null and b/public/pagefind/fragment/en_1b3734f.pf_fragment differ diff --git a/public/pagefind/fragment/en_1f7a77e.pf_fragment b/public/pagefind/fragment/en_1f7a77e.pf_fragment new file mode 100644 index 0000000..a52aabc Binary files /dev/null and b/public/pagefind/fragment/en_1f7a77e.pf_fragment differ diff --git a/public/pagefind/fragment/en_224aec9.pf_fragment b/public/pagefind/fragment/en_224aec9.pf_fragment new file mode 100644 index 0000000..703a6b7 Binary files /dev/null and b/public/pagefind/fragment/en_224aec9.pf_fragment differ diff --git a/public/pagefind/fragment/en_246cd7a.pf_fragment b/public/pagefind/fragment/en_246cd7a.pf_fragment new file mode 100644 index 0000000..df8b413 Binary files /dev/null and b/public/pagefind/fragment/en_246cd7a.pf_fragment differ diff --git a/public/pagefind/fragment/en_2882942.pf_fragment b/public/pagefind/fragment/en_2882942.pf_fragment new file mode 100644 index 0000000..c6ea407 Binary files /dev/null and b/public/pagefind/fragment/en_2882942.pf_fragment differ diff --git a/public/pagefind/fragment/en_2b1861e.pf_fragment b/public/pagefind/fragment/en_2b1861e.pf_fragment new file mode 100644 index 0000000..430a302 Binary files /dev/null and b/public/pagefind/fragment/en_2b1861e.pf_fragment differ diff --git a/public/pagefind/fragment/en_2e21b43.pf_fragment b/public/pagefind/fragment/en_2e21b43.pf_fragment new file mode 100644 index 0000000..e883a13 Binary files /dev/null and b/public/pagefind/fragment/en_2e21b43.pf_fragment differ diff --git a/public/pagefind/fragment/en_2e7a7d8.pf_fragment b/public/pagefind/fragment/en_2e7a7d8.pf_fragment new file mode 100644 index 0000000..231711c Binary files /dev/null and b/public/pagefind/fragment/en_2e7a7d8.pf_fragment differ diff --git a/public/pagefind/fragment/en_301fd63.pf_fragment b/public/pagefind/fragment/en_301fd63.pf_fragment new file mode 100644 index 0000000..f36679b Binary files /dev/null and b/public/pagefind/fragment/en_301fd63.pf_fragment differ diff --git a/public/pagefind/fragment/en_3571f45.pf_fragment b/public/pagefind/fragment/en_3571f45.pf_fragment new file mode 100644 index 0000000..1320f63 Binary files /dev/null and b/public/pagefind/fragment/en_3571f45.pf_fragment differ diff --git a/public/pagefind/fragment/en_39dd51e.pf_fragment b/public/pagefind/fragment/en_39dd51e.pf_fragment new file mode 100644 index 0000000..2f9dfcc Binary files /dev/null and b/public/pagefind/fragment/en_39dd51e.pf_fragment differ diff --git a/public/pagefind/fragment/en_3d3ee41.pf_fragment b/public/pagefind/fragment/en_3d3ee41.pf_fragment new file mode 100644 index 0000000..5a68986 Binary files /dev/null and b/public/pagefind/fragment/en_3d3ee41.pf_fragment differ diff --git a/public/pagefind/fragment/en_3f32cb2.pf_fragment b/public/pagefind/fragment/en_3f32cb2.pf_fragment new file mode 100644 index 0000000..85ad234 Binary files /dev/null and b/public/pagefind/fragment/en_3f32cb2.pf_fragment differ diff --git a/public/pagefind/fragment/en_41918d6.pf_fragment b/public/pagefind/fragment/en_41918d6.pf_fragment new file mode 100644 index 0000000..d2c7fbf Binary files /dev/null and b/public/pagefind/fragment/en_41918d6.pf_fragment differ diff --git a/public/pagefind/fragment/en_44ed5aa.pf_fragment b/public/pagefind/fragment/en_44ed5aa.pf_fragment new file mode 100644 index 0000000..997cd65 Binary files /dev/null and b/public/pagefind/fragment/en_44ed5aa.pf_fragment differ diff --git a/public/pagefind/fragment/en_4529964.pf_fragment b/public/pagefind/fragment/en_4529964.pf_fragment new file mode 100644 index 0000000..2851945 Binary files /dev/null and b/public/pagefind/fragment/en_4529964.pf_fragment differ diff --git a/public/pagefind/fragment/en_48f964a.pf_fragment b/public/pagefind/fragment/en_48f964a.pf_fragment new file mode 100644 index 0000000..77f3bfe Binary files /dev/null and b/public/pagefind/fragment/en_48f964a.pf_fragment differ diff --git a/public/pagefind/fragment/en_4a8c0bb.pf_fragment b/public/pagefind/fragment/en_4a8c0bb.pf_fragment new file mode 100644 index 0000000..2611790 Binary files /dev/null and b/public/pagefind/fragment/en_4a8c0bb.pf_fragment differ diff --git a/public/pagefind/fragment/en_4b64978.pf_fragment b/public/pagefind/fragment/en_4b64978.pf_fragment new file mode 100644 index 0000000..3dadd07 Binary files /dev/null and b/public/pagefind/fragment/en_4b64978.pf_fragment differ diff --git a/public/pagefind/fragment/en_51f72a9.pf_fragment b/public/pagefind/fragment/en_51f72a9.pf_fragment new file mode 100644 index 0000000..5b44dcd Binary files /dev/null and b/public/pagefind/fragment/en_51f72a9.pf_fragment differ diff --git a/public/pagefind/fragment/en_5489bb6.pf_fragment b/public/pagefind/fragment/en_5489bb6.pf_fragment new file mode 100644 index 0000000..4698145 Binary files /dev/null and b/public/pagefind/fragment/en_5489bb6.pf_fragment differ diff --git a/public/pagefind/fragment/en_5773ba2.pf_fragment b/public/pagefind/fragment/en_5773ba2.pf_fragment new file mode 100644 index 0000000..0951f2a Binary files /dev/null and b/public/pagefind/fragment/en_5773ba2.pf_fragment differ diff --git a/public/pagefind/fragment/en_5914ba5.pf_fragment b/public/pagefind/fragment/en_5914ba5.pf_fragment new file mode 100644 index 0000000..802f237 Binary files /dev/null and b/public/pagefind/fragment/en_5914ba5.pf_fragment differ diff --git a/public/pagefind/fragment/en_5b7b786.pf_fragment b/public/pagefind/fragment/en_5b7b786.pf_fragment new file mode 100644 index 0000000..f5ead7b Binary files /dev/null and b/public/pagefind/fragment/en_5b7b786.pf_fragment differ diff --git a/public/pagefind/fragment/en_5b91dc8.pf_fragment b/public/pagefind/fragment/en_5b91dc8.pf_fragment new file mode 100644 index 0000000..93c581a Binary files /dev/null and b/public/pagefind/fragment/en_5b91dc8.pf_fragment differ diff --git a/public/pagefind/fragment/en_5ef8a9e.pf_fragment b/public/pagefind/fragment/en_5ef8a9e.pf_fragment new file mode 100644 index 0000000..da67287 Binary files /dev/null and b/public/pagefind/fragment/en_5ef8a9e.pf_fragment differ diff --git a/public/pagefind/fragment/en_5f589a9.pf_fragment b/public/pagefind/fragment/en_5f589a9.pf_fragment new file mode 100644 index 0000000..4a70fad Binary files /dev/null and b/public/pagefind/fragment/en_5f589a9.pf_fragment differ diff --git a/public/pagefind/fragment/en_603c2fe.pf_fragment b/public/pagefind/fragment/en_603c2fe.pf_fragment new file mode 100644 index 0000000..eaf1d8d Binary files /dev/null and b/public/pagefind/fragment/en_603c2fe.pf_fragment differ diff --git a/public/pagefind/fragment/en_60cad05.pf_fragment b/public/pagefind/fragment/en_60cad05.pf_fragment new file mode 100644 index 0000000..350c08f Binary files /dev/null and b/public/pagefind/fragment/en_60cad05.pf_fragment differ diff --git a/public/pagefind/fragment/en_6364cb1.pf_fragment b/public/pagefind/fragment/en_6364cb1.pf_fragment new file mode 100644 index 0000000..701b1e9 Binary files /dev/null and b/public/pagefind/fragment/en_6364cb1.pf_fragment differ diff --git a/public/pagefind/fragment/en_64a0a4a.pf_fragment b/public/pagefind/fragment/en_64a0a4a.pf_fragment new file mode 100644 index 0000000..006724e Binary files /dev/null and b/public/pagefind/fragment/en_64a0a4a.pf_fragment differ diff --git a/public/pagefind/fragment/en_6545659.pf_fragment b/public/pagefind/fragment/en_6545659.pf_fragment new file mode 100644 index 0000000..55af45c Binary files /dev/null and b/public/pagefind/fragment/en_6545659.pf_fragment differ diff --git a/public/pagefind/fragment/en_65a9dab.pf_fragment b/public/pagefind/fragment/en_65a9dab.pf_fragment new file mode 100644 index 0000000..87ff36c Binary files /dev/null and b/public/pagefind/fragment/en_65a9dab.pf_fragment differ diff --git a/public/pagefind/fragment/en_677f7a3.pf_fragment b/public/pagefind/fragment/en_677f7a3.pf_fragment new file mode 100644 index 0000000..2f90387 Binary files /dev/null and b/public/pagefind/fragment/en_677f7a3.pf_fragment differ diff --git a/public/pagefind/fragment/en_69d1c29.pf_fragment b/public/pagefind/fragment/en_69d1c29.pf_fragment new file mode 100644 index 0000000..129b1dc Binary files /dev/null and b/public/pagefind/fragment/en_69d1c29.pf_fragment differ diff --git a/public/pagefind/fragment/en_6bac6b7.pf_fragment b/public/pagefind/fragment/en_6bac6b7.pf_fragment new file mode 100644 index 0000000..9cf72c6 Binary files /dev/null and b/public/pagefind/fragment/en_6bac6b7.pf_fragment differ diff --git a/public/pagefind/fragment/en_6de5b90.pf_fragment b/public/pagefind/fragment/en_6de5b90.pf_fragment new file mode 100644 index 0000000..a494509 Binary files /dev/null and b/public/pagefind/fragment/en_6de5b90.pf_fragment differ diff --git a/public/pagefind/fragment/en_6fb2269.pf_fragment b/public/pagefind/fragment/en_6fb2269.pf_fragment new file mode 100644 index 0000000..1407fbf Binary files /dev/null and b/public/pagefind/fragment/en_6fb2269.pf_fragment differ diff --git a/public/pagefind/fragment/en_71f8dec.pf_fragment b/public/pagefind/fragment/en_71f8dec.pf_fragment new file mode 100644 index 0000000..d805b63 Binary files /dev/null and b/public/pagefind/fragment/en_71f8dec.pf_fragment differ diff --git a/public/pagefind/fragment/en_77cead6.pf_fragment b/public/pagefind/fragment/en_77cead6.pf_fragment new file mode 100644 index 0000000..86aa344 Binary files /dev/null and b/public/pagefind/fragment/en_77cead6.pf_fragment differ diff --git a/public/pagefind/fragment/en_7c4170c.pf_fragment b/public/pagefind/fragment/en_7c4170c.pf_fragment new file mode 100644 index 0000000..1f568b8 Binary files /dev/null and b/public/pagefind/fragment/en_7c4170c.pf_fragment differ diff --git a/public/pagefind/fragment/en_7f1eb08.pf_fragment b/public/pagefind/fragment/en_7f1eb08.pf_fragment new file mode 100644 index 0000000..12f7ec2 Binary files /dev/null and b/public/pagefind/fragment/en_7f1eb08.pf_fragment differ diff --git a/public/pagefind/fragment/en_83edcec.pf_fragment b/public/pagefind/fragment/en_83edcec.pf_fragment new file mode 100644 index 0000000..2702ce6 Binary files /dev/null and b/public/pagefind/fragment/en_83edcec.pf_fragment differ diff --git a/public/pagefind/fragment/en_84e8e0e.pf_fragment b/public/pagefind/fragment/en_84e8e0e.pf_fragment new file mode 100644 index 0000000..db3a4f8 Binary files /dev/null and b/public/pagefind/fragment/en_84e8e0e.pf_fragment differ diff --git a/public/pagefind/fragment/en_86eeb15.pf_fragment b/public/pagefind/fragment/en_86eeb15.pf_fragment new file mode 100644 index 0000000..461d01f Binary files /dev/null and b/public/pagefind/fragment/en_86eeb15.pf_fragment differ diff --git a/public/pagefind/fragment/en_87ec5cc.pf_fragment b/public/pagefind/fragment/en_87ec5cc.pf_fragment new file mode 100644 index 0000000..1964fa3 Binary files /dev/null and b/public/pagefind/fragment/en_87ec5cc.pf_fragment differ diff --git a/public/pagefind/fragment/en_8a33086.pf_fragment b/public/pagefind/fragment/en_8a33086.pf_fragment new file mode 100644 index 0000000..bccb2a0 Binary files /dev/null and b/public/pagefind/fragment/en_8a33086.pf_fragment differ diff --git a/public/pagefind/fragment/en_8c3f224.pf_fragment b/public/pagefind/fragment/en_8c3f224.pf_fragment new file mode 100644 index 0000000..93e558c Binary files /dev/null and b/public/pagefind/fragment/en_8c3f224.pf_fragment differ diff --git a/public/pagefind/fragment/en_9189a3e.pf_fragment b/public/pagefind/fragment/en_9189a3e.pf_fragment new file mode 100644 index 0000000..209df43 Binary files /dev/null and b/public/pagefind/fragment/en_9189a3e.pf_fragment differ diff --git a/public/pagefind/fragment/en_977c978.pf_fragment b/public/pagefind/fragment/en_977c978.pf_fragment new file mode 100644 index 0000000..b7082f4 Binary files /dev/null and b/public/pagefind/fragment/en_977c978.pf_fragment differ diff --git a/public/pagefind/fragment/en_9bb1f6f.pf_fragment b/public/pagefind/fragment/en_9bb1f6f.pf_fragment new file mode 100644 index 0000000..5bdf5de Binary files /dev/null and b/public/pagefind/fragment/en_9bb1f6f.pf_fragment differ diff --git a/public/pagefind/fragment/en_9e89344.pf_fragment b/public/pagefind/fragment/en_9e89344.pf_fragment new file mode 100644 index 0000000..ef89357 Binary files /dev/null and b/public/pagefind/fragment/en_9e89344.pf_fragment differ diff --git a/public/pagefind/fragment/en_a43bd6c.pf_fragment b/public/pagefind/fragment/en_a43bd6c.pf_fragment new file mode 100644 index 0000000..e9434e9 Binary files /dev/null and b/public/pagefind/fragment/en_a43bd6c.pf_fragment differ diff --git a/public/pagefind/fragment/en_a5f691d.pf_fragment b/public/pagefind/fragment/en_a5f691d.pf_fragment new file mode 100644 index 0000000..5dafffd Binary files /dev/null and b/public/pagefind/fragment/en_a5f691d.pf_fragment differ diff --git a/public/pagefind/fragment/en_a61b702.pf_fragment b/public/pagefind/fragment/en_a61b702.pf_fragment new file mode 100644 index 0000000..6bd694a Binary files /dev/null and b/public/pagefind/fragment/en_a61b702.pf_fragment differ diff --git a/public/pagefind/fragment/en_a766912.pf_fragment b/public/pagefind/fragment/en_a766912.pf_fragment new file mode 100644 index 0000000..afa0eb3 Binary files /dev/null and b/public/pagefind/fragment/en_a766912.pf_fragment differ diff --git a/public/pagefind/fragment/en_a86e3f8.pf_fragment b/public/pagefind/fragment/en_a86e3f8.pf_fragment new file mode 100644 index 0000000..773e64d Binary files /dev/null and b/public/pagefind/fragment/en_a86e3f8.pf_fragment differ diff --git a/public/pagefind/fragment/en_a8ab335.pf_fragment b/public/pagefind/fragment/en_a8ab335.pf_fragment new file mode 100644 index 0000000..96b2c69 Binary files /dev/null and b/public/pagefind/fragment/en_a8ab335.pf_fragment differ diff --git a/public/pagefind/fragment/en_a9b3cd8.pf_fragment b/public/pagefind/fragment/en_a9b3cd8.pf_fragment new file mode 100644 index 0000000..33b0346 Binary files /dev/null and b/public/pagefind/fragment/en_a9b3cd8.pf_fragment differ diff --git a/public/pagefind/fragment/en_abca69d.pf_fragment b/public/pagefind/fragment/en_abca69d.pf_fragment new file mode 100644 index 0000000..b250960 Binary files /dev/null and b/public/pagefind/fragment/en_abca69d.pf_fragment differ diff --git a/public/pagefind/fragment/en_af369db.pf_fragment b/public/pagefind/fragment/en_af369db.pf_fragment new file mode 100644 index 0000000..9eae0fe Binary files /dev/null and b/public/pagefind/fragment/en_af369db.pf_fragment differ diff --git a/public/pagefind/fragment/en_b1a8f86.pf_fragment b/public/pagefind/fragment/en_b1a8f86.pf_fragment new file mode 100644 index 0000000..ec5e8e8 Binary files /dev/null and b/public/pagefind/fragment/en_b1a8f86.pf_fragment differ diff --git a/public/pagefind/fragment/en_b25f883.pf_fragment b/public/pagefind/fragment/en_b25f883.pf_fragment new file mode 100644 index 0000000..e2d97a4 Binary files /dev/null and b/public/pagefind/fragment/en_b25f883.pf_fragment differ diff --git a/public/pagefind/fragment/en_b3a4764.pf_fragment b/public/pagefind/fragment/en_b3a4764.pf_fragment new file mode 100644 index 0000000..153225a Binary files /dev/null and b/public/pagefind/fragment/en_b3a4764.pf_fragment differ diff --git a/public/pagefind/fragment/en_bb8c281.pf_fragment b/public/pagefind/fragment/en_bb8c281.pf_fragment new file mode 100644 index 0000000..70f64e0 Binary files /dev/null and b/public/pagefind/fragment/en_bb8c281.pf_fragment differ diff --git a/public/pagefind/fragment/en_bc1ce5d.pf_fragment b/public/pagefind/fragment/en_bc1ce5d.pf_fragment new file mode 100644 index 0000000..821c816 Binary files /dev/null and b/public/pagefind/fragment/en_bc1ce5d.pf_fragment differ diff --git a/public/pagefind/fragment/en_bcfa3a1.pf_fragment b/public/pagefind/fragment/en_bcfa3a1.pf_fragment new file mode 100644 index 0000000..06a7f90 Binary files /dev/null and b/public/pagefind/fragment/en_bcfa3a1.pf_fragment differ diff --git a/public/pagefind/fragment/en_bf96d98.pf_fragment b/public/pagefind/fragment/en_bf96d98.pf_fragment new file mode 100644 index 0000000..a8d5768 Binary files /dev/null and b/public/pagefind/fragment/en_bf96d98.pf_fragment differ diff --git a/public/pagefind/fragment/en_c086992.pf_fragment b/public/pagefind/fragment/en_c086992.pf_fragment new file mode 100644 index 0000000..e4b5305 Binary files /dev/null and b/public/pagefind/fragment/en_c086992.pf_fragment differ diff --git a/public/pagefind/fragment/en_c19bbcc.pf_fragment b/public/pagefind/fragment/en_c19bbcc.pf_fragment new file mode 100644 index 0000000..2528b61 Binary files /dev/null and b/public/pagefind/fragment/en_c19bbcc.pf_fragment differ diff --git a/public/pagefind/fragment/en_c5db944.pf_fragment b/public/pagefind/fragment/en_c5db944.pf_fragment new file mode 100644 index 0000000..f9b4874 Binary files /dev/null and b/public/pagefind/fragment/en_c5db944.pf_fragment differ diff --git a/public/pagefind/fragment/en_c7aef8f.pf_fragment b/public/pagefind/fragment/en_c7aef8f.pf_fragment new file mode 100644 index 0000000..52e8626 Binary files /dev/null and b/public/pagefind/fragment/en_c7aef8f.pf_fragment differ diff --git a/public/pagefind/fragment/en_c85be71.pf_fragment b/public/pagefind/fragment/en_c85be71.pf_fragment new file mode 100644 index 0000000..12c28ef Binary files /dev/null and b/public/pagefind/fragment/en_c85be71.pf_fragment differ diff --git a/public/pagefind/fragment/en_c9b61a3.pf_fragment b/public/pagefind/fragment/en_c9b61a3.pf_fragment new file mode 100644 index 0000000..8082d91 Binary files /dev/null and b/public/pagefind/fragment/en_c9b61a3.pf_fragment differ diff --git a/public/pagefind/fragment/en_cafa731.pf_fragment b/public/pagefind/fragment/en_cafa731.pf_fragment new file mode 100644 index 0000000..7ad6aeb Binary files /dev/null and b/public/pagefind/fragment/en_cafa731.pf_fragment differ diff --git a/public/pagefind/fragment/en_cbb8f64.pf_fragment b/public/pagefind/fragment/en_cbb8f64.pf_fragment new file mode 100644 index 0000000..d0ce2db Binary files /dev/null and b/public/pagefind/fragment/en_cbb8f64.pf_fragment differ diff --git a/public/pagefind/fragment/en_cda27be.pf_fragment b/public/pagefind/fragment/en_cda27be.pf_fragment new file mode 100644 index 0000000..0999e75 Binary files /dev/null and b/public/pagefind/fragment/en_cda27be.pf_fragment differ diff --git a/public/pagefind/fragment/en_d2263fb.pf_fragment b/public/pagefind/fragment/en_d2263fb.pf_fragment new file mode 100644 index 0000000..db48791 Binary files /dev/null and b/public/pagefind/fragment/en_d2263fb.pf_fragment differ diff --git a/public/pagefind/fragment/en_d328252.pf_fragment b/public/pagefind/fragment/en_d328252.pf_fragment new file mode 100644 index 0000000..3e073d3 Binary files /dev/null and b/public/pagefind/fragment/en_d328252.pf_fragment differ diff --git a/public/pagefind/fragment/en_d53649f.pf_fragment b/public/pagefind/fragment/en_d53649f.pf_fragment new file mode 100644 index 0000000..80be894 Binary files /dev/null and b/public/pagefind/fragment/en_d53649f.pf_fragment differ diff --git a/public/pagefind/fragment/en_d7d3e19.pf_fragment b/public/pagefind/fragment/en_d7d3e19.pf_fragment new file mode 100644 index 0000000..391384e Binary files /dev/null and b/public/pagefind/fragment/en_d7d3e19.pf_fragment differ diff --git a/public/pagefind/fragment/en_db10cab.pf_fragment b/public/pagefind/fragment/en_db10cab.pf_fragment new file mode 100644 index 0000000..aae13ce Binary files /dev/null and b/public/pagefind/fragment/en_db10cab.pf_fragment differ diff --git a/public/pagefind/fragment/en_db29521.pf_fragment b/public/pagefind/fragment/en_db29521.pf_fragment new file mode 100644 index 0000000..467f65e Binary files /dev/null and b/public/pagefind/fragment/en_db29521.pf_fragment differ diff --git a/public/pagefind/fragment/en_dbd042f.pf_fragment b/public/pagefind/fragment/en_dbd042f.pf_fragment new file mode 100644 index 0000000..256130f Binary files /dev/null and b/public/pagefind/fragment/en_dbd042f.pf_fragment differ diff --git a/public/pagefind/fragment/en_e04ee13.pf_fragment b/public/pagefind/fragment/en_e04ee13.pf_fragment new file mode 100644 index 0000000..c01e2a1 Binary files /dev/null and b/public/pagefind/fragment/en_e04ee13.pf_fragment differ diff --git a/public/pagefind/fragment/en_e0d2e37.pf_fragment b/public/pagefind/fragment/en_e0d2e37.pf_fragment new file mode 100644 index 0000000..a2ca2a8 Binary files /dev/null and b/public/pagefind/fragment/en_e0d2e37.pf_fragment differ diff --git a/public/pagefind/fragment/en_e1a97d6.pf_fragment b/public/pagefind/fragment/en_e1a97d6.pf_fragment new file mode 100644 index 0000000..1740944 Binary files /dev/null and b/public/pagefind/fragment/en_e1a97d6.pf_fragment differ diff --git a/public/pagefind/fragment/en_e4f448e.pf_fragment b/public/pagefind/fragment/en_e4f448e.pf_fragment new file mode 100644 index 0000000..5b24ec0 Binary files /dev/null and b/public/pagefind/fragment/en_e4f448e.pf_fragment differ diff --git a/public/pagefind/fragment/en_e58791c.pf_fragment b/public/pagefind/fragment/en_e58791c.pf_fragment new file mode 100644 index 0000000..83244fc Binary files /dev/null and b/public/pagefind/fragment/en_e58791c.pf_fragment differ diff --git a/public/pagefind/fragment/en_e59256e.pf_fragment b/public/pagefind/fragment/en_e59256e.pf_fragment new file mode 100644 index 0000000..df77974 Binary files /dev/null and b/public/pagefind/fragment/en_e59256e.pf_fragment differ diff --git a/public/pagefind/fragment/en_e8925de.pf_fragment b/public/pagefind/fragment/en_e8925de.pf_fragment new file mode 100644 index 0000000..6454083 Binary files /dev/null and b/public/pagefind/fragment/en_e8925de.pf_fragment differ diff --git a/public/pagefind/fragment/en_eb80583.pf_fragment b/public/pagefind/fragment/en_eb80583.pf_fragment new file mode 100644 index 0000000..6645fe7 Binary files /dev/null and b/public/pagefind/fragment/en_eb80583.pf_fragment differ diff --git a/public/pagefind/fragment/en_ef39419.pf_fragment b/public/pagefind/fragment/en_ef39419.pf_fragment new file mode 100644 index 0000000..e5bef5f Binary files /dev/null and b/public/pagefind/fragment/en_ef39419.pf_fragment differ diff --git a/public/pagefind/fragment/en_f0eb4d5.pf_fragment b/public/pagefind/fragment/en_f0eb4d5.pf_fragment new file mode 100644 index 0000000..66684e1 Binary files /dev/null and b/public/pagefind/fragment/en_f0eb4d5.pf_fragment differ diff --git a/public/pagefind/fragment/en_f3cb274.pf_fragment b/public/pagefind/fragment/en_f3cb274.pf_fragment new file mode 100644 index 0000000..97e9ce2 Binary files /dev/null and b/public/pagefind/fragment/en_f3cb274.pf_fragment differ diff --git a/public/pagefind/fragment/en_f87d165.pf_fragment b/public/pagefind/fragment/en_f87d165.pf_fragment new file mode 100644 index 0000000..1b7adff Binary files /dev/null and b/public/pagefind/fragment/en_f87d165.pf_fragment differ diff --git a/public/pagefind/index/en_1b1fa96.pf_index b/public/pagefind/index/en_1b1fa96.pf_index new file mode 100644 index 0000000..9d7d5c3 Binary files /dev/null and b/public/pagefind/index/en_1b1fa96.pf_index differ diff --git a/public/pagefind/index/en_53124bb.pf_index b/public/pagefind/index/en_53124bb.pf_index new file mode 100644 index 0000000..c0b4da0 Binary files /dev/null and b/public/pagefind/index/en_53124bb.pf_index differ diff --git a/public/pagefind/index/en_64aef84.pf_index b/public/pagefind/index/en_64aef84.pf_index new file mode 100644 index 0000000..f4260c2 Binary files /dev/null and b/public/pagefind/index/en_64aef84.pf_index differ diff --git a/public/pagefind/index/en_824db65.pf_index b/public/pagefind/index/en_824db65.pf_index new file mode 100644 index 0000000..d8406b9 Binary files /dev/null and b/public/pagefind/index/en_824db65.pf_index differ diff --git a/public/pagefind/index/en_9827e2a.pf_index b/public/pagefind/index/en_9827e2a.pf_index new file mode 100644 index 0000000..f856ada Binary files /dev/null and b/public/pagefind/index/en_9827e2a.pf_index differ diff --git a/public/pagefind/pagefind-entry.json b/public/pagefind/pagefind-entry.json new file mode 100644 index 0000000..144e047 --- /dev/null +++ b/public/pagefind/pagefind-entry.json @@ -0,0 +1 @@ +{"version":"1.3.0","languages":{"en":{"hash":"en_757c45eb84","wasm":"en","page_count":103}}} \ No newline at end of file diff --git a/public/pagefind/pagefind-highlight.js b/public/pagefind/pagefind-highlight.js new file mode 100644 index 0000000..c823fbf --- /dev/null +++ b/public/pagefind/pagefind-highlight.js @@ -0,0 +1,1069 @@ +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); + +// node_modules/mark.js/dist/mark.js +var require_mark = __commonJS({ + "node_modules/mark.js/dist/mark.js"(exports, module) { + (function(global, factory) { + typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : global.Mark = factory(); + })(exports, function() { + "use strict"; + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { + return typeof obj; + } : function(obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + var classCallCheck = function(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + }; + var createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) + descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) + defineProperties(Constructor.prototype, protoProps); + if (staticProps) + defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _extends = Object.assign || function(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + return target; + }; + var DOMIterator = function() { + function DOMIterator2(ctx) { + var iframes = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true; + var exclude = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : []; + var iframesTimeout = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : 5e3; + classCallCheck(this, DOMIterator2); + this.ctx = ctx; + this.iframes = iframes; + this.exclude = exclude; + this.iframesTimeout = iframesTimeout; + } + createClass(DOMIterator2, [{ + key: "getContexts", + value: function getContexts() { + var ctx = void 0, filteredCtx = []; + if (typeof this.ctx === "undefined" || !this.ctx) { + ctx = []; + } else if (NodeList.prototype.isPrototypeOf(this.ctx)) { + ctx = Array.prototype.slice.call(this.ctx); + } else if (Array.isArray(this.ctx)) { + ctx = this.ctx; + } else if (typeof this.ctx === "string") { + ctx = Array.prototype.slice.call(document.querySelectorAll(this.ctx)); + } else { + ctx = [this.ctx]; + } + ctx.forEach(function(ctx2) { + var isDescendant = filteredCtx.filter(function(contexts) { + return contexts.contains(ctx2); + }).length > 0; + if (filteredCtx.indexOf(ctx2) === -1 && !isDescendant) { + filteredCtx.push(ctx2); + } + }); + return filteredCtx; + } + }, { + key: "getIframeContents", + value: function getIframeContents(ifr, successFn) { + var errorFn = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : function() { + }; + var doc = void 0; + try { + var ifrWin = ifr.contentWindow; + doc = ifrWin.document; + if (!ifrWin || !doc) { + throw new Error("iframe inaccessible"); + } + } catch (e) { + errorFn(); + } + if (doc) { + successFn(doc); + } + } + }, { + key: "isIframeBlank", + value: function isIframeBlank(ifr) { + var bl = "about:blank", src = ifr.getAttribute("src").trim(), href = ifr.contentWindow.location.href; + return href === bl && src !== bl && src; + } + }, { + key: "observeIframeLoad", + value: function observeIframeLoad(ifr, successFn, errorFn) { + var _this = this; + var called = false, tout = null; + var listener = function listener2() { + if (called) { + return; + } + called = true; + clearTimeout(tout); + try { + if (!_this.isIframeBlank(ifr)) { + ifr.removeEventListener("load", listener2); + _this.getIframeContents(ifr, successFn, errorFn); + } + } catch (e) { + errorFn(); + } + }; + ifr.addEventListener("load", listener); + tout = setTimeout(listener, this.iframesTimeout); + } + }, { + key: "onIframeReady", + value: function onIframeReady(ifr, successFn, errorFn) { + try { + if (ifr.contentWindow.document.readyState === "complete") { + if (this.isIframeBlank(ifr)) { + this.observeIframeLoad(ifr, successFn, errorFn); + } else { + this.getIframeContents(ifr, successFn, errorFn); + } + } else { + this.observeIframeLoad(ifr, successFn, errorFn); + } + } catch (e) { + errorFn(); + } + } + }, { + key: "waitForIframes", + value: function waitForIframes(ctx, done) { + var _this2 = this; + var eachCalled = 0; + this.forEachIframe(ctx, function() { + return true; + }, function(ifr) { + eachCalled++; + _this2.waitForIframes(ifr.querySelector("html"), function() { + if (!--eachCalled) { + done(); + } + }); + }, function(handled) { + if (!handled) { + done(); + } + }); + } + }, { + key: "forEachIframe", + value: function forEachIframe(ctx, filter, each) { + var _this3 = this; + var end = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : function() { + }; + var ifr = ctx.querySelectorAll("iframe"), open = ifr.length, handled = 0; + ifr = Array.prototype.slice.call(ifr); + var checkEnd = function checkEnd2() { + if (--open <= 0) { + end(handled); + } + }; + if (!open) { + checkEnd(); + } + ifr.forEach(function(ifr2) { + if (DOMIterator2.matches(ifr2, _this3.exclude)) { + checkEnd(); + } else { + _this3.onIframeReady(ifr2, function(con) { + if (filter(ifr2)) { + handled++; + each(con); + } + checkEnd(); + }, checkEnd); + } + }); + } + }, { + key: "createIterator", + value: function createIterator(ctx, whatToShow, filter) { + return document.createNodeIterator(ctx, whatToShow, filter, false); + } + }, { + key: "createInstanceOnIframe", + value: function createInstanceOnIframe(contents) { + return new DOMIterator2(contents.querySelector("html"), this.iframes); + } + }, { + key: "compareNodeIframe", + value: function compareNodeIframe(node, prevNode, ifr) { + var compCurr = node.compareDocumentPosition(ifr), prev = Node.DOCUMENT_POSITION_PRECEDING; + if (compCurr & prev) { + if (prevNode !== null) { + var compPrev = prevNode.compareDocumentPosition(ifr), after = Node.DOCUMENT_POSITION_FOLLOWING; + if (compPrev & after) { + return true; + } + } else { + return true; + } + } + return false; + } + }, { + key: "getIteratorNode", + value: function getIteratorNode(itr) { + var prevNode = itr.previousNode(); + var node = void 0; + if (prevNode === null) { + node = itr.nextNode(); + } else { + node = itr.nextNode() && itr.nextNode(); + } + return { + prevNode, + node + }; + } + }, { + key: "checkIframeFilter", + value: function checkIframeFilter(node, prevNode, currIfr, ifr) { + var key = false, handled = false; + ifr.forEach(function(ifrDict, i) { + if (ifrDict.val === currIfr) { + key = i; + handled = ifrDict.handled; + } + }); + if (this.compareNodeIframe(node, prevNode, currIfr)) { + if (key === false && !handled) { + ifr.push({ + val: currIfr, + handled: true + }); + } else if (key !== false && !handled) { + ifr[key].handled = true; + } + return true; + } + if (key === false) { + ifr.push({ + val: currIfr, + handled: false + }); + } + return false; + } + }, { + key: "handleOpenIframes", + value: function handleOpenIframes(ifr, whatToShow, eCb, fCb) { + var _this4 = this; + ifr.forEach(function(ifrDict) { + if (!ifrDict.handled) { + _this4.getIframeContents(ifrDict.val, function(con) { + _this4.createInstanceOnIframe(con).forEachNode(whatToShow, eCb, fCb); + }); + } + }); + } + }, { + key: "iterateThroughNodes", + value: function iterateThroughNodes(whatToShow, ctx, eachCb, filterCb, doneCb) { + var _this5 = this; + var itr = this.createIterator(ctx, whatToShow, filterCb); + var ifr = [], elements = [], node = void 0, prevNode = void 0, retrieveNodes = function retrieveNodes2() { + var _getIteratorNode = _this5.getIteratorNode(itr); + prevNode = _getIteratorNode.prevNode; + node = _getIteratorNode.node; + return node; + }; + while (retrieveNodes()) { + if (this.iframes) { + this.forEachIframe(ctx, function(currIfr) { + return _this5.checkIframeFilter(node, prevNode, currIfr, ifr); + }, function(con) { + _this5.createInstanceOnIframe(con).forEachNode(whatToShow, function(ifrNode) { + return elements.push(ifrNode); + }, filterCb); + }); + } + elements.push(node); + } + elements.forEach(function(node2) { + eachCb(node2); + }); + if (this.iframes) { + this.handleOpenIframes(ifr, whatToShow, eachCb, filterCb); + } + doneCb(); + } + }, { + key: "forEachNode", + value: function forEachNode(whatToShow, each, filter) { + var _this6 = this; + var done = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : function() { + }; + var contexts = this.getContexts(); + var open = contexts.length; + if (!open) { + done(); + } + contexts.forEach(function(ctx) { + var ready = function ready2() { + _this6.iterateThroughNodes(whatToShow, ctx, each, filter, function() { + if (--open <= 0) { + done(); + } + }); + }; + if (_this6.iframes) { + _this6.waitForIframes(ctx, ready); + } else { + ready(); + } + }); + } + }], [{ + key: "matches", + value: function matches(element, selector) { + var selectors = typeof selector === "string" ? [selector] : selector, fn = element.matches || element.matchesSelector || element.msMatchesSelector || element.mozMatchesSelector || element.oMatchesSelector || element.webkitMatchesSelector; + if (fn) { + var match = false; + selectors.every(function(sel) { + if (fn.call(element, sel)) { + match = true; + return false; + } + return true; + }); + return match; + } else { + return false; + } + } + }]); + return DOMIterator2; + }(); + var Mark$1 = function() { + function Mark3(ctx) { + classCallCheck(this, Mark3); + this.ctx = ctx; + this.ie = false; + var ua = window.navigator.userAgent; + if (ua.indexOf("MSIE") > -1 || ua.indexOf("Trident") > -1) { + this.ie = true; + } + } + createClass(Mark3, [{ + key: "log", + value: function log(msg) { + var level = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "debug"; + var log2 = this.opt.log; + if (!this.opt.debug) { + return; + } + if ((typeof log2 === "undefined" ? "undefined" : _typeof(log2)) === "object" && typeof log2[level] === "function") { + log2[level]("mark.js: " + msg); + } + } + }, { + key: "escapeStr", + value: function escapeStr(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + } + }, { + key: "createRegExp", + value: function createRegExp(str) { + if (this.opt.wildcards !== "disabled") { + str = this.setupWildcardsRegExp(str); + } + str = this.escapeStr(str); + if (Object.keys(this.opt.synonyms).length) { + str = this.createSynonymsRegExp(str); + } + if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) { + str = this.setupIgnoreJoinersRegExp(str); + } + if (this.opt.diacritics) { + str = this.createDiacriticsRegExp(str); + } + str = this.createMergedBlanksRegExp(str); + if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) { + str = this.createJoinersRegExp(str); + } + if (this.opt.wildcards !== "disabled") { + str = this.createWildcardsRegExp(str); + } + str = this.createAccuracyRegExp(str); + return str; + } + }, { + key: "createSynonymsRegExp", + value: function createSynonymsRegExp(str) { + var syn = this.opt.synonyms, sens = this.opt.caseSensitive ? "" : "i", joinerPlaceholder = this.opt.ignoreJoiners || this.opt.ignorePunctuation.length ? "\0" : ""; + for (var index in syn) { + if (syn.hasOwnProperty(index)) { + var value = syn[index], k1 = this.opt.wildcards !== "disabled" ? this.setupWildcardsRegExp(index) : this.escapeStr(index), k2 = this.opt.wildcards !== "disabled" ? this.setupWildcardsRegExp(value) : this.escapeStr(value); + if (k1 !== "" && k2 !== "") { + str = str.replace(new RegExp("(" + this.escapeStr(k1) + "|" + this.escapeStr(k2) + ")", "gm" + sens), joinerPlaceholder + ("(" + this.processSynomyms(k1) + "|") + (this.processSynomyms(k2) + ")") + joinerPlaceholder); + } + } + } + return str; + } + }, { + key: "processSynomyms", + value: function processSynomyms(str) { + if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) { + str = this.setupIgnoreJoinersRegExp(str); + } + return str; + } + }, { + key: "setupWildcardsRegExp", + value: function setupWildcardsRegExp(str) { + str = str.replace(/(?:\\)*\?/g, function(val) { + return val.charAt(0) === "\\" ? "?" : ""; + }); + return str.replace(/(?:\\)*\*/g, function(val) { + return val.charAt(0) === "\\" ? "*" : ""; + }); + } + }, { + key: "createWildcardsRegExp", + value: function createWildcardsRegExp(str) { + var spaces = this.opt.wildcards === "withSpaces"; + return str.replace(/\u0001/g, spaces ? "[\\S\\s]?" : "\\S?").replace(/\u0002/g, spaces ? "[\\S\\s]*?" : "\\S*"); + } + }, { + key: "setupIgnoreJoinersRegExp", + value: function setupIgnoreJoinersRegExp(str) { + return str.replace(/[^(|)\\]/g, function(val, indx, original) { + var nextChar = original.charAt(indx + 1); + if (/[(|)\\]/.test(nextChar) || nextChar === "") { + return val; + } else { + return val + "\0"; + } + }); + } + }, { + key: "createJoinersRegExp", + value: function createJoinersRegExp(str) { + var joiner = []; + var ignorePunctuation = this.opt.ignorePunctuation; + if (Array.isArray(ignorePunctuation) && ignorePunctuation.length) { + joiner.push(this.escapeStr(ignorePunctuation.join(""))); + } + if (this.opt.ignoreJoiners) { + joiner.push("\\u00ad\\u200b\\u200c\\u200d"); + } + return joiner.length ? str.split(/\u0000+/).join("[" + joiner.join("") + "]*") : str; + } + }, { + key: "createDiacriticsRegExp", + value: function createDiacriticsRegExp(str) { + var sens = this.opt.caseSensitive ? "" : "i", dct = this.opt.caseSensitive ? ["a\xE0\xE1\u1EA3\xE3\u1EA1\u0103\u1EB1\u1EAF\u1EB3\u1EB5\u1EB7\xE2\u1EA7\u1EA5\u1EA9\u1EAB\u1EAD\xE4\xE5\u0101\u0105", "A\xC0\xC1\u1EA2\xC3\u1EA0\u0102\u1EB0\u1EAE\u1EB2\u1EB4\u1EB6\xC2\u1EA6\u1EA4\u1EA8\u1EAA\u1EAC\xC4\xC5\u0100\u0104", "c\xE7\u0107\u010D", "C\xC7\u0106\u010C", "d\u0111\u010F", "D\u0110\u010E", "e\xE8\xE9\u1EBB\u1EBD\u1EB9\xEA\u1EC1\u1EBF\u1EC3\u1EC5\u1EC7\xEB\u011B\u0113\u0119", "E\xC8\xC9\u1EBA\u1EBC\u1EB8\xCA\u1EC0\u1EBE\u1EC2\u1EC4\u1EC6\xCB\u011A\u0112\u0118", "i\xEC\xED\u1EC9\u0129\u1ECB\xEE\xEF\u012B", "I\xCC\xCD\u1EC8\u0128\u1ECA\xCE\xCF\u012A", "l\u0142", "L\u0141", "n\xF1\u0148\u0144", "N\xD1\u0147\u0143", "o\xF2\xF3\u1ECF\xF5\u1ECD\xF4\u1ED3\u1ED1\u1ED5\u1ED7\u1ED9\u01A1\u1EDF\u1EE1\u1EDB\u1EDD\u1EE3\xF6\xF8\u014D", "O\xD2\xD3\u1ECE\xD5\u1ECC\xD4\u1ED2\u1ED0\u1ED4\u1ED6\u1ED8\u01A0\u1EDE\u1EE0\u1EDA\u1EDC\u1EE2\xD6\xD8\u014C", "r\u0159", "R\u0158", "s\u0161\u015B\u0219\u015F", "S\u0160\u015A\u0218\u015E", "t\u0165\u021B\u0163", "T\u0164\u021A\u0162", "u\xF9\xFA\u1EE7\u0169\u1EE5\u01B0\u1EEB\u1EE9\u1EED\u1EEF\u1EF1\xFB\xFC\u016F\u016B", "U\xD9\xDA\u1EE6\u0168\u1EE4\u01AF\u1EEA\u1EE8\u1EEC\u1EEE\u1EF0\xDB\xDC\u016E\u016A", "y\xFD\u1EF3\u1EF7\u1EF9\u1EF5\xFF", "Y\xDD\u1EF2\u1EF6\u1EF8\u1EF4\u0178", "z\u017E\u017C\u017A", "Z\u017D\u017B\u0179"] : ["a\xE0\xE1\u1EA3\xE3\u1EA1\u0103\u1EB1\u1EAF\u1EB3\u1EB5\u1EB7\xE2\u1EA7\u1EA5\u1EA9\u1EAB\u1EAD\xE4\xE5\u0101\u0105A\xC0\xC1\u1EA2\xC3\u1EA0\u0102\u1EB0\u1EAE\u1EB2\u1EB4\u1EB6\xC2\u1EA6\u1EA4\u1EA8\u1EAA\u1EAC\xC4\xC5\u0100\u0104", "c\xE7\u0107\u010DC\xC7\u0106\u010C", "d\u0111\u010FD\u0110\u010E", "e\xE8\xE9\u1EBB\u1EBD\u1EB9\xEA\u1EC1\u1EBF\u1EC3\u1EC5\u1EC7\xEB\u011B\u0113\u0119E\xC8\xC9\u1EBA\u1EBC\u1EB8\xCA\u1EC0\u1EBE\u1EC2\u1EC4\u1EC6\xCB\u011A\u0112\u0118", "i\xEC\xED\u1EC9\u0129\u1ECB\xEE\xEF\u012BI\xCC\xCD\u1EC8\u0128\u1ECA\xCE\xCF\u012A", "l\u0142L\u0141", "n\xF1\u0148\u0144N\xD1\u0147\u0143", "o\xF2\xF3\u1ECF\xF5\u1ECD\xF4\u1ED3\u1ED1\u1ED5\u1ED7\u1ED9\u01A1\u1EDF\u1EE1\u1EDB\u1EDD\u1EE3\xF6\xF8\u014DO\xD2\xD3\u1ECE\xD5\u1ECC\xD4\u1ED2\u1ED0\u1ED4\u1ED6\u1ED8\u01A0\u1EDE\u1EE0\u1EDA\u1EDC\u1EE2\xD6\xD8\u014C", "r\u0159R\u0158", "s\u0161\u015B\u0219\u015FS\u0160\u015A\u0218\u015E", "t\u0165\u021B\u0163T\u0164\u021A\u0162", "u\xF9\xFA\u1EE7\u0169\u1EE5\u01B0\u1EEB\u1EE9\u1EED\u1EEF\u1EF1\xFB\xFC\u016F\u016BU\xD9\xDA\u1EE6\u0168\u1EE4\u01AF\u1EEA\u1EE8\u1EEC\u1EEE\u1EF0\xDB\xDC\u016E\u016A", "y\xFD\u1EF3\u1EF7\u1EF9\u1EF5\xFFY\xDD\u1EF2\u1EF6\u1EF8\u1EF4\u0178", "z\u017E\u017C\u017AZ\u017D\u017B\u0179"]; + var handled = []; + str.split("").forEach(function(ch) { + dct.every(function(dct2) { + if (dct2.indexOf(ch) !== -1) { + if (handled.indexOf(dct2) > -1) { + return false; + } + str = str.replace(new RegExp("[" + dct2 + "]", "gm" + sens), "[" + dct2 + "]"); + handled.push(dct2); + } + return true; + }); + }); + return str; + } + }, { + key: "createMergedBlanksRegExp", + value: function createMergedBlanksRegExp(str) { + return str.replace(/[\s]+/gmi, "[\\s]+"); + } + }, { + key: "createAccuracyRegExp", + value: function createAccuracyRegExp(str) { + var _this = this; + var chars = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\xA1\xBF"; + var acc = this.opt.accuracy, val = typeof acc === "string" ? acc : acc.value, ls = typeof acc === "string" ? [] : acc.limiters, lsJoin = ""; + ls.forEach(function(limiter) { + lsJoin += "|" + _this.escapeStr(limiter); + }); + switch (val) { + case "partially": + default: + return "()(" + str + ")"; + case "complementary": + lsJoin = "\\s" + (lsJoin ? lsJoin : this.escapeStr(chars)); + return "()([^" + lsJoin + "]*" + str + "[^" + lsJoin + "]*)"; + case "exactly": + return "(^|\\s" + lsJoin + ")(" + str + ")(?=$|\\s" + lsJoin + ")"; + } + } + }, { + key: "getSeparatedKeywords", + value: function getSeparatedKeywords(sv) { + var _this2 = this; + var stack = []; + sv.forEach(function(kw) { + if (!_this2.opt.separateWordSearch) { + if (kw.trim() && stack.indexOf(kw) === -1) { + stack.push(kw); + } + } else { + kw.split(" ").forEach(function(kwSplitted) { + if (kwSplitted.trim() && stack.indexOf(kwSplitted) === -1) { + stack.push(kwSplitted); + } + }); + } + }); + return { + "keywords": stack.sort(function(a, b) { + return b.length - a.length; + }), + "length": stack.length + }; + } + }, { + key: "isNumeric", + value: function isNumeric(value) { + return Number(parseFloat(value)) == value; + } + }, { + key: "checkRanges", + value: function checkRanges(array) { + var _this3 = this; + if (!Array.isArray(array) || Object.prototype.toString.call(array[0]) !== "[object Object]") { + this.log("markRanges() will only accept an array of objects"); + this.opt.noMatch(array); + return []; + } + var stack = []; + var last = 0; + array.sort(function(a, b) { + return a.start - b.start; + }).forEach(function(item) { + var _callNoMatchOnInvalid = _this3.callNoMatchOnInvalidRanges(item, last), start = _callNoMatchOnInvalid.start, end = _callNoMatchOnInvalid.end, valid = _callNoMatchOnInvalid.valid; + if (valid) { + item.start = start; + item.length = end - start; + stack.push(item); + last = end; + } + }); + return stack; + } + }, { + key: "callNoMatchOnInvalidRanges", + value: function callNoMatchOnInvalidRanges(range, last) { + var start = void 0, end = void 0, valid = false; + if (range && typeof range.start !== "undefined") { + start = parseInt(range.start, 10); + end = start + parseInt(range.length, 10); + if (this.isNumeric(range.start) && this.isNumeric(range.length) && end - last > 0 && end - start > 0) { + valid = true; + } else { + this.log("Ignoring invalid or overlapping range: " + ("" + JSON.stringify(range))); + this.opt.noMatch(range); + } + } else { + this.log("Ignoring invalid range: " + JSON.stringify(range)); + this.opt.noMatch(range); + } + return { + start, + end, + valid + }; + } + }, { + key: "checkWhitespaceRanges", + value: function checkWhitespaceRanges(range, originalLength, string) { + var end = void 0, valid = true, max = string.length, offset = originalLength - max, start = parseInt(range.start, 10) - offset; + start = start > max ? max : start; + end = start + parseInt(range.length, 10); + if (end > max) { + end = max; + this.log("End range automatically set to the max value of " + max); + } + if (start < 0 || end - start < 0 || start > max || end > max) { + valid = false; + this.log("Invalid range: " + JSON.stringify(range)); + this.opt.noMatch(range); + } else if (string.substring(start, end).replace(/\s+/g, "") === "") { + valid = false; + this.log("Skipping whitespace only range: " + JSON.stringify(range)); + this.opt.noMatch(range); + } + return { + start, + end, + valid + }; + } + }, { + key: "getTextNodes", + value: function getTextNodes(cb) { + var _this4 = this; + var val = "", nodes = []; + this.iterator.forEachNode(NodeFilter.SHOW_TEXT, function(node) { + nodes.push({ + start: val.length, + end: (val += node.textContent).length, + node + }); + }, function(node) { + if (_this4.matchesExclude(node.parentNode)) { + return NodeFilter.FILTER_REJECT; + } else { + return NodeFilter.FILTER_ACCEPT; + } + }, function() { + cb({ + value: val, + nodes + }); + }); + } + }, { + key: "matchesExclude", + value: function matchesExclude(el) { + return DOMIterator.matches(el, this.opt.exclude.concat(["script", "style", "title", "head", "html"])); + } + }, { + key: "wrapRangeInTextNode", + value: function wrapRangeInTextNode(node, start, end) { + var hEl = !this.opt.element ? "mark" : this.opt.element, startNode = node.splitText(start), ret = startNode.splitText(end - start); + var repl = document.createElement(hEl); + repl.setAttribute("data-markjs", "true"); + if (this.opt.className) { + repl.setAttribute("class", this.opt.className); + } + repl.textContent = startNode.textContent; + startNode.parentNode.replaceChild(repl, startNode); + return ret; + } + }, { + key: "wrapRangeInMappedTextNode", + value: function wrapRangeInMappedTextNode(dict, start, end, filterCb, eachCb) { + var _this5 = this; + dict.nodes.every(function(n, i) { + var sibl = dict.nodes[i + 1]; + if (typeof sibl === "undefined" || sibl.start > start) { + if (!filterCb(n.node)) { + return false; + } + var s = start - n.start, e = (end > n.end ? n.end : end) - n.start, startStr = dict.value.substr(0, n.start), endStr = dict.value.substr(e + n.start); + n.node = _this5.wrapRangeInTextNode(n.node, s, e); + dict.value = startStr + endStr; + dict.nodes.forEach(function(k, j) { + if (j >= i) { + if (dict.nodes[j].start > 0 && j !== i) { + dict.nodes[j].start -= e; + } + dict.nodes[j].end -= e; + } + }); + end -= e; + eachCb(n.node.previousSibling, n.start); + if (end > n.end) { + start = n.end; + } else { + return false; + } + } + return true; + }); + } + }, { + key: "wrapMatches", + value: function wrapMatches(regex, ignoreGroups, filterCb, eachCb, endCb) { + var _this6 = this; + var matchIdx = ignoreGroups === 0 ? 0 : ignoreGroups + 1; + this.getTextNodes(function(dict) { + dict.nodes.forEach(function(node) { + node = node.node; + var match = void 0; + while ((match = regex.exec(node.textContent)) !== null && match[matchIdx] !== "") { + if (!filterCb(match[matchIdx], node)) { + continue; + } + var pos = match.index; + if (matchIdx !== 0) { + for (var i = 1; i < matchIdx; i++) { + pos += match[i].length; + } + } + node = _this6.wrapRangeInTextNode(node, pos, pos + match[matchIdx].length); + eachCb(node.previousSibling); + regex.lastIndex = 0; + } + }); + endCb(); + }); + } + }, { + key: "wrapMatchesAcrossElements", + value: function wrapMatchesAcrossElements(regex, ignoreGroups, filterCb, eachCb, endCb) { + var _this7 = this; + var matchIdx = ignoreGroups === 0 ? 0 : ignoreGroups + 1; + this.getTextNodes(function(dict) { + var match = void 0; + while ((match = regex.exec(dict.value)) !== null && match[matchIdx] !== "") { + var start = match.index; + if (matchIdx !== 0) { + for (var i = 1; i < matchIdx; i++) { + start += match[i].length; + } + } + var end = start + match[matchIdx].length; + _this7.wrapRangeInMappedTextNode(dict, start, end, function(node) { + return filterCb(match[matchIdx], node); + }, function(node, lastIndex) { + regex.lastIndex = lastIndex; + eachCb(node); + }); + } + endCb(); + }); + } + }, { + key: "wrapRangeFromIndex", + value: function wrapRangeFromIndex(ranges, filterCb, eachCb, endCb) { + var _this8 = this; + this.getTextNodes(function(dict) { + var originalLength = dict.value.length; + ranges.forEach(function(range, counter) { + var _checkWhitespaceRange = _this8.checkWhitespaceRanges(range, originalLength, dict.value), start = _checkWhitespaceRange.start, end = _checkWhitespaceRange.end, valid = _checkWhitespaceRange.valid; + if (valid) { + _this8.wrapRangeInMappedTextNode(dict, start, end, function(node) { + return filterCb(node, range, dict.value.substring(start, end), counter); + }, function(node) { + eachCb(node, range); + }); + } + }); + endCb(); + }); + } + }, { + key: "unwrapMatches", + value: function unwrapMatches(node) { + var parent = node.parentNode; + var docFrag = document.createDocumentFragment(); + while (node.firstChild) { + docFrag.appendChild(node.removeChild(node.firstChild)); + } + parent.replaceChild(docFrag, node); + if (!this.ie) { + parent.normalize(); + } else { + this.normalizeTextNode(parent); + } + } + }, { + key: "normalizeTextNode", + value: function normalizeTextNode(node) { + if (!node) { + return; + } + if (node.nodeType === 3) { + while (node.nextSibling && node.nextSibling.nodeType === 3) { + node.nodeValue += node.nextSibling.nodeValue; + node.parentNode.removeChild(node.nextSibling); + } + } else { + this.normalizeTextNode(node.firstChild); + } + this.normalizeTextNode(node.nextSibling); + } + }, { + key: "markRegExp", + value: function markRegExp(regexp, opt) { + var _this9 = this; + this.opt = opt; + this.log('Searching with expression "' + regexp + '"'); + var totalMatches = 0, fn = "wrapMatches"; + var eachCb = function eachCb2(element) { + totalMatches++; + _this9.opt.each(element); + }; + if (this.opt.acrossElements) { + fn = "wrapMatchesAcrossElements"; + } + this[fn](regexp, this.opt.ignoreGroups, function(match, node) { + return _this9.opt.filter(node, match, totalMatches); + }, eachCb, function() { + if (totalMatches === 0) { + _this9.opt.noMatch(regexp); + } + _this9.opt.done(totalMatches); + }); + } + }, { + key: "mark", + value: function mark(sv, opt) { + var _this10 = this; + this.opt = opt; + var totalMatches = 0, fn = "wrapMatches"; + var _getSeparatedKeywords = this.getSeparatedKeywords(typeof sv === "string" ? [sv] : sv), kwArr = _getSeparatedKeywords.keywords, kwArrLen = _getSeparatedKeywords.length, sens = this.opt.caseSensitive ? "" : "i", handler = function handler2(kw) { + var regex = new RegExp(_this10.createRegExp(kw), "gm" + sens), matches = 0; + _this10.log('Searching with expression "' + regex + '"'); + _this10[fn](regex, 1, function(term, node) { + return _this10.opt.filter(node, kw, totalMatches, matches); + }, function(element) { + matches++; + totalMatches++; + _this10.opt.each(element); + }, function() { + if (matches === 0) { + _this10.opt.noMatch(kw); + } + if (kwArr[kwArrLen - 1] === kw) { + _this10.opt.done(totalMatches); + } else { + handler2(kwArr[kwArr.indexOf(kw) + 1]); + } + }); + }; + if (this.opt.acrossElements) { + fn = "wrapMatchesAcrossElements"; + } + if (kwArrLen === 0) { + this.opt.done(totalMatches); + } else { + handler(kwArr[0]); + } + } + }, { + key: "markRanges", + value: function markRanges(rawRanges, opt) { + var _this11 = this; + this.opt = opt; + var totalMatches = 0, ranges = this.checkRanges(rawRanges); + if (ranges && ranges.length) { + this.log("Starting to mark with the following ranges: " + JSON.stringify(ranges)); + this.wrapRangeFromIndex(ranges, function(node, range, match, counter) { + return _this11.opt.filter(node, range, match, counter); + }, function(element, range) { + totalMatches++; + _this11.opt.each(element, range); + }, function() { + _this11.opt.done(totalMatches); + }); + } else { + this.opt.done(totalMatches); + } + } + }, { + key: "unmark", + value: function unmark(opt) { + var _this12 = this; + this.opt = opt; + var sel = this.opt.element ? this.opt.element : "*"; + sel += "[data-markjs]"; + if (this.opt.className) { + sel += "." + this.opt.className; + } + this.log('Removal selector "' + sel + '"'); + this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT, function(node) { + _this12.unwrapMatches(node); + }, function(node) { + var matchesSel = DOMIterator.matches(node, sel), matchesExclude = _this12.matchesExclude(node); + if (!matchesSel || matchesExclude) { + return NodeFilter.FILTER_REJECT; + } else { + return NodeFilter.FILTER_ACCEPT; + } + }, this.opt.done); + } + }, { + key: "opt", + set: function set$$1(val) { + this._opt = _extends({}, { + "element": "", + "className": "", + "exclude": [], + "iframes": false, + "iframesTimeout": 5e3, + "separateWordSearch": true, + "diacritics": true, + "synonyms": {}, + "accuracy": "partially", + "acrossElements": false, + "caseSensitive": false, + "ignoreJoiners": false, + "ignoreGroups": 0, + "ignorePunctuation": [], + "wildcards": "disabled", + "each": function each() { + }, + "noMatch": function noMatch() { + }, + "filter": function filter() { + return true; + }, + "done": function done() { + }, + "debug": false, + "log": window.console + }, val); + }, + get: function get$$1() { + return this._opt; + } + }, { + key: "iterator", + get: function get$$1() { + return new DOMIterator(this.ctx, this.opt.iframes, this.opt.exclude, this.opt.iframesTimeout); + } + }]); + return Mark3; + }(); + function Mark2(ctx) { + var _this = this; + var instance = new Mark$1(ctx); + this.mark = function(sv, opt) { + instance.mark(sv, opt); + return _this; + }; + this.markRegExp = function(sv, opt) { + instance.markRegExp(sv, opt); + return _this; + }; + this.markRanges = function(sv, opt) { + instance.markRanges(sv, opt); + return _this; + }; + this.unmark = function(opt) { + instance.unmark(opt); + return _this; + }; + return this; + } + return Mark2; + }); + } +}); + +// lib/highlight.ts +var import_mark = __toESM(require_mark(), 1); +var PagefindHighlight = class { + constructor(options = { + markContext: null, + highlightParam: "pagefind-highlight", + markOptions: { + className: "pagefind-highlight", + exclude: ["[data-pagefind-ignore]", "[data-pagefind-ignore] *"] + }, + addStyles: true + }) { + var _a, _b; + const { highlightParam, markContext, markOptions, addStyles } = options; + this.highlightParam = highlightParam ?? "pagefind-highlight"; + this.addStyles = addStyles ?? true; + this.markContext = markContext !== void 0 ? markContext : null; + this.markOptions = markOptions !== void 0 ? markOptions : { + className: "pagefind-highlight", + exclude: ["[data-pagefind-ignore]", "[data-pagefind-ignore] *"] + }; + (_a = this.markOptions).className ?? (_a.className = "pagefind__highlight"); + (_b = this.markOptions).exclude ?? (_b.exclude = [ + "[data-pagefind-ignore]", + "[data-pagefind-ignore] *" + ]); + this.markOptions.separateWordSearch = false; + this.highlight(); + } + getHighlightParams(paramName) { + const urlParams = new URLSearchParams(window.location.search); + return urlParams.getAll(paramName); + } + // Inline styles might be too hard to override + addHighlightStyles(className) { + if (!className) + return; + const styleElement = document.createElement("style"); + styleElement.innerText = `:where(.${className}) { background-color: yellow; color: black; }`; + document.head.appendChild(styleElement); + } + createMarkInstance() { + if (this.markContext) { + return new import_mark.default(this.markContext); + } + const pagefindBody = document.querySelectorAll("[data-pagefind-body]"); + if (pagefindBody.length !== 0) { + return new import_mark.default(pagefindBody); + } else { + return new import_mark.default(document.body); + } + } + markText(instance, text) { + instance.mark(text, this.markOptions); + } + highlight() { + const params = this.getHighlightParams(this.highlightParam); + if (!params || params.length === 0) + return; + this.addStyles && this.addHighlightStyles(this.markOptions.className); + const markInstance = this.createMarkInstance(); + this.markText(markInstance, params); + } +}; +window.PagefindHighlight = PagefindHighlight; +export { + PagefindHighlight as default +}; +/*! Bundled license information: + +mark.js/dist/mark.js: + (*!*************************************************** + * mark.js v8.11.1 + * https://markjs.io/ + * Copyright (c) 2014–2018, Julian Kühnel + * Released under the MIT license https://git.io/vwTVl + *****************************************************) +*/ diff --git a/public/pagefind/pagefind-modular-ui.css b/public/pagefind/pagefind-modular-ui.css new file mode 100644 index 0000000..9c6793e --- /dev/null +++ b/public/pagefind/pagefind-modular-ui.css @@ -0,0 +1,214 @@ +:root { + --pagefind-ui-scale: 0.8; + --pagefind-ui-primary: #034AD8; + --pagefind-ui-fade: #707070; + --pagefind-ui-text: #393939; + --pagefind-ui-background: #ffffff; + --pagefind-ui-border: #eeeeee; + --pagefind-ui-tag: #eeeeee; + --pagefind-ui-border-width: 2px; + --pagefind-ui-border-radius: 8px; + --pagefind-ui-image-border-radius: 8px; + --pagefind-ui-image-box-ratio: 3 / 2; + --pagefind-ui-font: system, -apple-system, ".SFNSText-Regular", + "San Francisco", "Roboto", "Segoe UI", "Helvetica Neue", + "Lucida Grande", sans-serif; +} + +[data-pfmod-hidden] { + display: none !important; +} + +[data-pfmod-suppressed] { + opacity: 0 !important; + pointer-events: none !important; +} + +[data-pfmod-sr-hidden] { + -webkit-clip: rect(0 0 0 0) !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + height: 1px !important; + overflow: hidden !important; + overflow: clip !important; + position: absolute !important; + white-space: nowrap !important; + width: 1px !important; +} + +[data-pfmod-loading] { + color: var(--pagefind-ui-text); + background-color: var(--pagefind-ui-text); + border-radius: var(--pagefind-ui-border-radius); + opacity: 0.1; + pointer-events: none; +} + +/* Input */ + +.pagefind-modular-input-wrapper { + position: relative; +} + +.pagefind-modular-input-wrapper::before { + background-color: var(--pagefind-ui-text); + width: calc(18px * var(--pagefind-ui-scale)); + height: calc(18px * var(--pagefind-ui-scale)); + top: calc(23px * var(--pagefind-ui-scale)); + left: calc(20px * var(--pagefind-ui-scale)); + content: ""; + position: absolute; + display: block; + opacity: 0.7; + -webkit-mask-image: url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A"); + mask-image: url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A"); + -webkit-mask-size: 100%; + mask-size: 100%; + z-index: 9; + pointer-events: none; +} + +.pagefind-modular-input { + height: calc(64px * var(--pagefind-ui-scale)); + padding: 0 calc(70px * var(--pagefind-ui-scale)) 0 calc(54px * var(--pagefind-ui-scale)); + background-color: var(--pagefind-ui-background); + border: var(--pagefind-ui-border-width) solid var(--pagefind-ui-border); + border-radius: var(--pagefind-ui-border-radius); + font-size: calc(21px * var(--pagefind-ui-scale)); + position: relative; + appearance: none; + -webkit-appearance: none; + display: flex; + width: 100%; + box-sizing: border-box; + font-weight: 700; +} + +.pagefind-modular-input::placeholder { + opacity: 0.2; +} + +.pagefind-modular-input-clear { + position: absolute; + top: calc(2px * var(--pagefind-ui-scale)); + right: calc(2px * var(--pagefind-ui-scale)); + height: calc(60px * var(--pagefind-ui-scale)); + border-radius: var(--pagefind-ui-border-radius); + padding: 0 calc(15px * var(--pagefind-ui-scale)) 0 calc(2px * var(--pagefind-ui-scale)); + color: var(--pagefind-ui-text); + font-size: calc(14px * var(--pagefind-ui-scale)); + cursor: pointer; + background-color: var(--pagefind-ui-background); + border: none; + appearance: none; +} + +/* ResultList */ + +.pagefind-modular-list-result { + list-style-type: none; + display: flex; + align-items: flex-start; + gap: min(calc(40px * var(--pagefind-ui-scale)), 3%); + padding: calc(30px * var(--pagefind-ui-scale)) 0 calc(40px * var(--pagefind-ui-scale)); + border-top: solid var(--pagefind-ui-border-width) var(--pagefind-ui-border); +} + +.pagefind-modular-list-result:last-of-type { + border-bottom: solid var(--pagefind-ui-border-width) var(--pagefind-ui-border); +} + +.pagefind-modular-list-thumb { + width: min(30%, + calc((30% - (100px * var(--pagefind-ui-scale))) * 100000)); + max-width: calc(120px * var(--pagefind-ui-scale)); + margin-top: calc(10px * var(--pagefind-ui-scale)); + aspect-ratio: var(--pagefind-ui-image-box-ratio); + position: relative; +} + +.pagefind-modular-list-image { + display: block; + position: absolute; + left: 50%; + transform: translateX(-50%); + font-size: 0; + width: auto; + height: auto; + max-width: 100%; + max-height: 100%; + border-radius: var(--pagefind-ui-image-border-radius); +} + +.pagefind-modular-list-inner { + flex: 1; + display: flex; + flex-direction: column; + align-items: flex-start; + margin-top: calc(10px * var(--pagefind-ui-scale)); +} + +.pagefind-modular-list-title { + display: inline-block; + font-weight: 700; + font-size: calc(21px * var(--pagefind-ui-scale)); + margin-top: 0; + margin-bottom: 0; +} + +.pagefind-modular-list-link { + color: var(--pagefind-ui-text); + text-decoration: none; +} + +.pagefind-modular-list-link:hover { + text-decoration: underline; +} + +.pagefind-modular-list-excerpt { + display: inline-block; + font-weight: 400; + font-size: calc(16px * var(--pagefind-ui-scale)); + margin-top: calc(4px * var(--pagefind-ui-scale)); + margin-bottom: 0; + min-width: calc(250px * var(--pagefind-ui-scale)); +} + +/* FilterPills */ + +.pagefind-modular-filter-pills-wrapper { + overflow-x: scroll; + padding: 15px 0; +} + +.pagefind-modular-filter-pills { + display: flex; + gap: 6px; +} + +.pagefind-modular-filter-pill { + display: flex; + justify-content: center; + align-items: center; + border: none; + appearance: none; + padding: 0 calc(24px * var(--pagefind-ui-scale)); + background-color: var(--pagefind-ui-background); + color: var(--pagefind-ui-fade); + border: var(--pagefind-ui-border-width) solid var(--pagefind-ui-border); + border-radius: calc(25px * var(--pagefind-ui-scale)); + font-size: calc(18px * var(--pagefind-ui-scale)); + height: calc(50px * var(--pagefind-ui-scale)); + cursor: pointer; + white-space: nowrap; +} + +.pagefind-modular-filter-pill:hover { + border-color: var(--pagefind-ui-primary); +} + +.pagefind-modular-filter-pill[aria-pressed="true"] { + border-color: var(--pagefind-ui-primary); + color: var(--pagefind-ui-primary); +} \ No newline at end of file diff --git a/public/pagefind/pagefind-modular-ui.js b/public/pagefind/pagefind-modular-ui.js new file mode 100644 index 0000000..43f738f --- /dev/null +++ b/public/pagefind/pagefind-modular-ui.js @@ -0,0 +1,8 @@ +(()=>{var b=Object.defineProperty;var w=(i,e)=>{for(var t in e)b(i,t,{get:e[t],enumerable:!0})};var f={};w(f,{FilterPills:()=>h,Input:()=>l,Instance:()=>p,ResultList:()=>a,Summary:()=>o});var r=class i{constructor(e){this.element=document.createElement(e)}id(e){return this.element.id=e,this}class(e){return this.element.classList.add(e),this}attrs(e){for(let[t,s]of Object.entries(e))this.element.setAttribute(t,s);return this}text(e){return this.element.innerText=e,this}html(e){return this.element.innerHTML=e,this}handle(e,t){return this.element.addEventListener(e,t),this}addTo(e){return e instanceof i?e.element.appendChild(this.element):e.appendChild(this.element),this.element}};var T=async(i=100)=>new Promise(e=>setTimeout(e,i)),l=class{constructor(e={}){if(this.inputEl=null,this.clearEl=null,this.instance=null,this.searchID=0,this.debounceTimeoutMs=e.debounceTimeoutMs??300,e.inputElement){if(e.containerElement){console.warn("[Pagefind Input component]: inputElement and containerElement both supplied. Ignoring the container option.");return}this.initExisting(e.inputElement)}else if(e.containerElement)this.initContainer(e.containerElement);else{console.error("[Pagefind Input component]: No selector supplied for containerElement or inputElement");return}this.inputEl.addEventListener("input",async t=>{if(this.instance&&typeof t?.target?.value=="string"){this.updateState(t.target.value);let s=++this.searchID;if(await T(this.debounceTimeoutMs),s!==this.searchID)return null;this.instance?.triggerSearch(t.target.value)}}),this.inputEl.addEventListener("keydown",t=>{t.key==="Escape"&&(++this.searchID,this.inputEl.value="",this.instance?.triggerSearch(""),this.updateState("")),t.key==="Enter"&&t.preventDefault()}),this.inputEl.addEventListener("focus",()=>{this.instance?.triggerLoad()})}initContainer(e){let t=document.querySelector(e);if(!t){console.error(`[Pagefind Input component]: No container found for ${e} selector`);return}if(t.tagName==="INPUT")console.warn(`[Pagefind Input component]: Encountered input element for ${e} when a container was expected`),console.warn("[Pagefind Input component]: Treating containerElement option as inputElement and proceeding"),this.initExisting(e);else{t.innerHTML="";let s=0;for(;document.querySelector(`#pfmod-input-${s}`);)s+=1;let n=new r("form").class("pagefind-modular-input-wrapper").attrs({role:"search","aria-label":"Search this site",action:"javascript:void(0);"});new r("label").attrs({for:`pfmod-input-${s}`,"data-pfmod-sr-hidden":"true"}).text("Search this site").addTo(n),this.inputEl=new r("input").id(`pfmod-input-${s}`).class("pagefind-modular-input").attrs({autocapitalize:"none",enterkeyhint:"search"}).addTo(n),this.clearEl=new r("button").class("pagefind-modular-input-clear").attrs({"data-pfmod-suppressed":"true"}).text("Clear").handle("click",()=>{this.inputEl.value="",this.instance.triggerSearch(""),this.updateState("")}).addTo(n),n.addTo(t)}}initExisting(e){let t=document.querySelector(e);if(!t){console.error(`[Pagefind Input component]: No input element found for ${e} selector`);return}if(t.tagName!=="INPUT"){console.error(`[Pagefind Input component]: Expected ${e} to be an element`);return}this.inputEl=t}updateState(e){this.clearEl&&(e&&e?.length?this.clearEl.removeAttribute("data-pfmod-suppressed"):this.clearEl.setAttribute("data-pfmod-suppressed","true"))}register(e){this.instance=e,this.instance.on("search",(t,s)=>{this.inputEl&&document.activeElement!==this.inputEl&&(this.inputEl.value=t,this.updateState(t))})}focus(){this.inputEl&&this.inputEl.focus()}};var g=i=>{if(i instanceof Element)return[i];if(Array.isArray(i)&&i.every(e=>e instanceof Element))return i;if(typeof i=="string"||i instanceof String){let e=document.createElement("div");return e.innerHTML=i,[...e.childNodes]}else return console.error(`[Pagefind ResultList component]: Expected template function to return an HTML element or string, got ${typeof i}`),[]},v=()=>{let i=(e=30)=>". ".repeat(Math.floor(10+Math.random()*e));return`
  • +
    +
    +

    ${i(30)}

    +

    ${i(40)}

    +
    +
  • `},y=i=>{let e=new r("li").class("pagefind-modular-list-result"),t=new r("div").class("pagefind-modular-list-thumb").addTo(e);i?.meta?.image&&new r("img").class("pagefind-modular-list-image").attrs({src:i.meta.image,alt:i.meta.image_alt||i.meta.title}).addTo(t);let s=new r("div").class("pagefind-modular-list-inner").addTo(e),n=new r("p").class("pagefind-modular-list-title").addTo(s);return new r("a").class("pagefind-modular-list-link").text(i.meta?.title).attrs({href:i.meta?.url||i.url}).addTo(n),new r("p").class("pagefind-modular-list-excerpt").html(i.excerpt).addTo(s),e.element},E=i=>{if(!(i instanceof HTMLElement))return null;let e=window.getComputedStyle(i).overflowY;return e!=="visible"&&e!=="hidden"?i:E(i.parentNode)},d=class{constructor(e={}){this.rawResult=e.result,this.placeholderNodes=e.placeholderNodes,this.resultFn=e.resultFn,this.intersectionEl=e.intersectionEl,this.result=null,this.waitForIntersection()}waitForIntersection(){if(!this.placeholderNodes?.length)return;let e={root:this.intersectionEl,rootMargin:"0px",threshold:.01};new IntersectionObserver((s,n)=>{this.result===null&&s?.[0]?.isIntersecting&&(this.load(),n.disconnect())},e).observe(this.placeholderNodes[0])}async load(){if(!this.placeholderNodes?.length)return;this.result=await this.rawResult.data();let e=this.resultFn(this.result),t=g(e);for(;this.placeholderNodes.length>1;)this.placeholderNodes.pop().remove();this.placeholderNodes[0].replaceWith(...t)}},a=class{constructor(e){if(this.intersectionEl=document.body,this.containerEl=null,this.results=[],this.placeholderTemplate=e.placeholderTemplate??v,this.resultTemplate=e.resultTemplate??y,e.containerElement)this.initContainer(e.containerElement);else{console.error("[Pagefind ResultList component]: No selector supplied for containerElement");return}}initContainer(e){let t=document.querySelector(e);if(!t){console.error(`[Pagefind ResultList component]: No container found for ${e} selector`);return}this.containerEl=t}append(e){for(let t of e)this.containerEl.appendChild(t)}register(e){e.on("results",t=>{this.containerEl&&(this.containerEl.innerHTML="",this.intersectionEl=E(this.containerEl),this.results=t.results.map(s=>{let n=g(this.placeholderTemplate());return this.append(n),new d({result:s,placeholderNodes:n,resultFn:this.resultTemplate,intersectionEl:this.intersectionEl})}))}),e.on("loading",()=>{this.containerEl&&(this.containerEl.innerHTML="")})}};var o=class{constructor(e={}){if(this.containerEl=null,this.defaultMessage=e.defaultMessage??"",this.term="",e.containerElement)this.initContainer(e.containerElement);else{console.error("[Pagefind Summary component]: No selector supplied for containerElement");return}}initContainer(e){let t=document.querySelector(e);if(!t){console.error(`[Pagefind Summary component]: No container found for ${e} selector`);return}this.containerEl=t,this.containerEl.innerText=this.defaultMessage}register(e){e.on("search",(t,s)=>{this.term=t}),e.on("results",t=>{if(!this.containerEl||!t)return;if(!this.term){this.containerEl.innerText=this.defaultMessage;return}let s=t?.results?.length??0;this.containerEl.innerText=`${s} result${s===1?"":"s"} for ${this.term}`}),e.on("loading",()=>{this.containerEl&&(this.containerEl.innerText=`Searching for ${this.term}...`)})}};var h=class{constructor(e={}){if(this.instance=null,this.wrapper=null,this.pillContainer=null,this.available={},this.selected=["All"],this.total=0,this.filterMemo="",this.filter=e.filter,this.ordering=e.ordering??null,this.alwaysShow=e.alwaysShow??!1,this.selectMultiple=e.selectMultiple??!1,!this.filter?.length){console.error("[Pagefind FilterPills component]: No filter option supplied, nothing to display");return}if(e.containerElement)this.initContainer(e.containerElement);else{console.error("[Pagefind FilterPills component]: No selector supplied for containerElement");return}}initContainer(e){let t=document.querySelector(e);if(!t){console.error(`[Pagefind FilterPills component]: No container found for ${e} selector`);return}t.innerHTML="";let s=`pagefind_modular_filter_pills_${this.filter}`,n=new r("div").class("pagefind-modular-filter-pills-wrapper").attrs({role:"group","aria-labelledby":s});this.alwaysShow||n.attrs({"data-pfmod-hidden":!0}),new r("div").id(s).class("pagefind-modular-filter-pills-label").attrs({"data-pfmod-sr-hidden":!0}).text(`Filter results by ${this.filter}`).addTo(n),this.pillContainer=new r("div").class("pagefind-modular-filter-pills").addTo(n),this.wrapper=n.addTo(t)}update(){let e=this.available.map(t=>t[0]).join("~");e==this.filterMemo?this.updateExisting():(this.renderNew(),this.filterMemo=e)}pushFilters(){let e=this.selected.filter(t=>t!=="All");this.instance.triggerFilter(this.filter,e)}pillInner(e,t){return this.total?`${e} (${t})`:`${e}`}renderNew(){this.available.forEach(([e,t])=>{new r("button").class("pagefind-modular-filter-pill").html(this.pillInner(e,t)).attrs({"aria-pressed":this.selected.includes(e),type:"button"}).handle("click",()=>{e==="All"?this.selected=["All"]:this.selected.includes(e)?this.selected=this.selected.filter(s=>s!==e):this.selectMultiple?this.selected.push(e):this.selected=[e],this.selected?.length?this.selected?.length>1&&(this.selected=this.selected.filter(s=>s!=="All")):this.selected=["All"],this.update(),this.pushFilters()}).addTo(this.pillContainer)})}updateExisting(){let e=[...this.pillContainer.childNodes];this.available.forEach(([t,s],n)=>{e[n].innerHTML=this.pillInner(t,s),e[n].setAttribute("aria-pressed",this.selected.includes(t))})}register(e){this.instance=e,this.instance.on("filters",t=>{if(!this.pillContainer)return;this.selectMultiple?t=t.available:t=t.total;let s=t[this.filter];if(!s){console.warn(`[Pagefind FilterPills component]: No possible values found for the ${this.filter} filter`);return}this.available=Object.entries(s),Array.isArray(this.ordering)?this.available.sort((n,c)=>{let m=this.ordering.indexOf(n[0]),_=this.ordering.indexOf(c[0]);return(m===-1?1/0:m)-(_===-1?1/0:_)}):this.available.sort((n,c)=>n[0].localeCompare(c[0])),this.available.unshift(["All",this.total]),this.update()}),e.on("results",t=>{this.pillContainer&&(this.total=t?.unfilteredResultCount||0,this.available?.[0]?.[0]==="All"&&(this.available[0][1]=this.total),this.total||this.alwaysShow?this.wrapper.removeAttribute("data-pfmod-hidden"):this.wrapper.setAttribute("data-pfmod-hidden","true"),this.update())})}};var P=async(i=50)=>await new Promise(e=>setTimeout(e,i)),u;try{document?.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"&&(u=new URL(document.currentScript.src).pathname.match(/^(.*\/)(?:pagefind-)?modular-ui.js.*$/)[1])}catch{u="/pagefind/"}var p=class{constructor(e={}){this.__pagefind__=null,this.__initializing__=null,this.__searchID__=0,this.__hooks__={search:[],filters:[],loading:[],results:[]},this.components=[],this.searchTerm="",this.searchFilters={},this.searchResult={},this.availableFilters=null,this.totalFilters=null,this.options={bundlePath:e.bundlePath??u,mergeIndex:e.mergeIndex??[]},delete e.bundlePath,delete e.resetStyles,delete e.processResult,delete e.processTerm,delete e.debounceTimeoutMs,delete e.mergeIndex,delete e.translations,this.pagefindOptions=e}add(e){e?.register?.(this),this.components.push(e)}on(e,t){if(!this.__hooks__[e]){let s=Object.keys(this.__hooks__).join(", ");console.error(`[Pagefind Composable]: Unknown event type ${e}. Supported events: [${s}]`);return}if(typeof t!="function"){console.error(`[Pagefind Composable]: Expected callback to be a function, received ${typeof t}`);return}this.__hooks__[e].push(t)}triggerLoad(){this.__load__()}triggerSearch(e){this.searchTerm=e,this.__dispatch__("search",e,this.searchFilters),this.__search__(e,this.searchFilters)}triggerSearchWithFilters(e,t){this.searchTerm=e,this.searchFilters=t,this.__dispatch__("search",e,t),this.__search__(e,t)}triggerFilters(e){this.searchFilters=e,this.__dispatch__("search",this.searchTerm,e),this.__search__(this.searchTerm,e)}triggerFilter(e,t){this.searchFilters=this.searchFilters||{},this.searchFilters[e]=t,this.__dispatch__("search",this.searchTerm,this.searchFilters),this.__search__(this.searchTerm,this.searchFilters)}__dispatch__(e,...t){this.__hooks__[e]?.forEach(s=>s?.(...t))}async __clear__(){this.__dispatch__("results",{results:[],unfilteredTotalCount:0}),this.availableFilters=await this.__pagefind__.filters(),this.totalFilters=this.availableFilters,this.__dispatch__("filters",{available:this.availableFilters,total:this.totalFilters})}async __search__(e,t){this.__dispatch__("loading"),await this.__load__();let s=++this.__searchID__;if(!e||!e.length)return this.__clear__();let n=await this.__pagefind__.search(e,{filters:t});n&&this.__searchID__===s&&(n.filters&&Object.keys(n.filters)?.length&&(this.availableFilters=n.filters,this.totalFilters=n.totalFilters,this.__dispatch__("filters",{available:this.availableFilters,total:this.totalFilters})),this.searchResult=n,this.__dispatch__("results",this.searchResult))}async __load__(){if(this.__initializing__){for(;!this.__pagefind__;)await P(50);return}if(this.__initializing__=!0,!this.__pagefind__){let e;try{e=await import(`${this.options.bundlePath}pagefind.js`)}catch(t){console.error(t),console.error([`Pagefind couldn't be loaded from ${this.options.bundlePath}pagefind.js`,"You can configure this by passing a bundlePath option to PagefindComposable Instance"].join(` +`)),document?.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?console.error(`[DEBUG: Loaded from ${document.currentScript?.src??"bad script location"}]`):console.error("no known script location")}await e.options(this.pagefindOptions||{});for(let t of this.options.mergeIndex){if(!t.bundlePath)throw new Error("mergeIndex requires a bundlePath parameter");let s=t.bundlePath;delete t.bundlePath,await e.mergeIndex(s,t)}this.__pagefind__=e}this.availableFilters=await this.__pagefind__.filters(),this.totalFilters=this.availableFilters,this.__dispatch__("filters",{available:this.availableFilters,total:this.totalFilters})}};window.PagefindModularUI=f;})(); diff --git a/public/pagefind/pagefind-ui.css b/public/pagefind/pagefind-ui.css new file mode 100644 index 0000000..d7984a9 --- /dev/null +++ b/public/pagefind/pagefind-ui.css @@ -0,0 +1 @@ +.pagefind-ui__result.svelte-j9e30.svelte-j9e30{list-style-type:none;display:flex;align-items:flex-start;gap:min(calc(40px * var(--pagefind-ui-scale)),3%);padding:calc(30px * var(--pagefind-ui-scale)) 0 calc(40px * var(--pagefind-ui-scale));border-top:solid var(--pagefind-ui-border-width) var(--pagefind-ui-border)}.pagefind-ui__result.svelte-j9e30.svelte-j9e30:last-of-type{border-bottom:solid var(--pagefind-ui-border-width) var(--pagefind-ui-border)}.pagefind-ui__result-thumb.svelte-j9e30.svelte-j9e30{width:min(30%,calc((30% - (100px * var(--pagefind-ui-scale))) * 100000));max-width:calc(120px * var(--pagefind-ui-scale));margin-top:calc(10px * var(--pagefind-ui-scale));aspect-ratio:var(--pagefind-ui-image-box-ratio);position:relative}.pagefind-ui__result-image.svelte-j9e30.svelte-j9e30{display:block;position:absolute;left:50%;transform:translate(-50%);font-size:0;width:auto;height:auto;max-width:100%;max-height:100%;border-radius:var(--pagefind-ui-image-border-radius)}.pagefind-ui__result-inner.svelte-j9e30.svelte-j9e30{flex:1;display:flex;flex-direction:column;align-items:flex-start;margin-top:calc(10px * var(--pagefind-ui-scale))}.pagefind-ui__result-title.svelte-j9e30.svelte-j9e30{display:inline-block;font-weight:700;font-size:calc(21px * var(--pagefind-ui-scale));margin-top:0;margin-bottom:0}.pagefind-ui__result-title.svelte-j9e30 .pagefind-ui__result-link.svelte-j9e30{color:var(--pagefind-ui-text);text-decoration:none}.pagefind-ui__result-title.svelte-j9e30 .pagefind-ui__result-link.svelte-j9e30:hover{text-decoration:underline}.pagefind-ui__result-excerpt.svelte-j9e30.svelte-j9e30{display:inline-block;font-weight:400;font-size:calc(16px * var(--pagefind-ui-scale));margin-top:calc(4px * var(--pagefind-ui-scale));margin-bottom:0;min-width:calc(250px * var(--pagefind-ui-scale))}.pagefind-ui__loading.svelte-j9e30.svelte-j9e30{color:var(--pagefind-ui-text);background-color:var(--pagefind-ui-text);border-radius:var(--pagefind-ui-border-radius);opacity:.1;pointer-events:none}.pagefind-ui__result-tags.svelte-j9e30.svelte-j9e30{list-style-type:none;padding:0;display:flex;gap:calc(20px * var(--pagefind-ui-scale));flex-wrap:wrap;margin-top:calc(20px * var(--pagefind-ui-scale))}.pagefind-ui__result-tag.svelte-j9e30.svelte-j9e30{padding:calc(4px * var(--pagefind-ui-scale)) calc(8px * var(--pagefind-ui-scale));font-size:calc(14px * var(--pagefind-ui-scale));border-radius:var(--pagefind-ui-border-radius);background-color:var(--pagefind-ui-tag)}.pagefind-ui__result.svelte-4xnkmf.svelte-4xnkmf{list-style-type:none;display:flex;align-items:flex-start;gap:min(calc(40px * var(--pagefind-ui-scale)),3%);padding:calc(30px * var(--pagefind-ui-scale)) 0 calc(40px * var(--pagefind-ui-scale));border-top:solid var(--pagefind-ui-border-width) var(--pagefind-ui-border)}.pagefind-ui__result.svelte-4xnkmf.svelte-4xnkmf:last-of-type{border-bottom:solid var(--pagefind-ui-border-width) var(--pagefind-ui-border)}.pagefind-ui__result-nested.svelte-4xnkmf.svelte-4xnkmf{display:flex;flex-direction:column;padding-left:calc(20px * var(--pagefind-ui-scale))}.pagefind-ui__result-nested.svelte-4xnkmf.svelte-4xnkmf:first-of-type{padding-top:calc(10px * var(--pagefind-ui-scale))}.pagefind-ui__result-nested.svelte-4xnkmf .pagefind-ui__result-link.svelte-4xnkmf{font-size:.9em;position:relative}.pagefind-ui__result-nested.svelte-4xnkmf .pagefind-ui__result-link.svelte-4xnkmf:before{content:"\2937 ";position:absolute;top:0;right:calc(100% + .1em)}.pagefind-ui__result-thumb.svelte-4xnkmf.svelte-4xnkmf{width:min(30%,calc((30% - (100px * var(--pagefind-ui-scale))) * 100000));max-width:calc(120px * var(--pagefind-ui-scale));margin-top:calc(10px * var(--pagefind-ui-scale));aspect-ratio:var(--pagefind-ui-image-box-ratio);position:relative}.pagefind-ui__result-image.svelte-4xnkmf.svelte-4xnkmf{display:block;position:absolute;left:50%;transform:translate(-50%);font-size:0;width:auto;height:auto;max-width:100%;max-height:100%;border-radius:var(--pagefind-ui-image-border-radius)}.pagefind-ui__result-inner.svelte-4xnkmf.svelte-4xnkmf{flex:1;display:flex;flex-direction:column;align-items:flex-start;margin-top:calc(10px * var(--pagefind-ui-scale))}.pagefind-ui__result-title.svelte-4xnkmf.svelte-4xnkmf{display:inline-block;font-weight:700;font-size:calc(21px * var(--pagefind-ui-scale));margin-top:0;margin-bottom:0}.pagefind-ui__result-title.svelte-4xnkmf .pagefind-ui__result-link.svelte-4xnkmf{color:var(--pagefind-ui-text);text-decoration:none}.pagefind-ui__result-title.svelte-4xnkmf .pagefind-ui__result-link.svelte-4xnkmf:hover{text-decoration:underline}.pagefind-ui__result-excerpt.svelte-4xnkmf.svelte-4xnkmf{display:inline-block;font-weight:400;font-size:calc(16px * var(--pagefind-ui-scale));margin-top:calc(4px * var(--pagefind-ui-scale));margin-bottom:0;min-width:calc(250px * var(--pagefind-ui-scale))}.pagefind-ui__loading.svelte-4xnkmf.svelte-4xnkmf{color:var(--pagefind-ui-text);background-color:var(--pagefind-ui-text);border-radius:var(--pagefind-ui-border-radius);opacity:.1;pointer-events:none}.pagefind-ui__result-tags.svelte-4xnkmf.svelte-4xnkmf{list-style-type:none;padding:0;display:flex;gap:calc(20px * var(--pagefind-ui-scale));flex-wrap:wrap;margin-top:calc(20px * var(--pagefind-ui-scale))}.pagefind-ui__result-tag.svelte-4xnkmf.svelte-4xnkmf{padding:calc(4px * var(--pagefind-ui-scale)) calc(8px * var(--pagefind-ui-scale));font-size:calc(14px * var(--pagefind-ui-scale));border-radius:var(--pagefind-ui-border-radius);background-color:var(--pagefind-ui-tag)}legend.svelte-1v2r7ls.svelte-1v2r7ls{position:absolute;clip:rect(0 0 0 0)}.pagefind-ui__filter-panel.svelte-1v2r7ls.svelte-1v2r7ls{min-width:min(calc(260px * var(--pagefind-ui-scale)),100%);flex:1;display:flex;flex-direction:column;margin-top:calc(20px * var(--pagefind-ui-scale))}.pagefind-ui__filter-group.svelte-1v2r7ls.svelte-1v2r7ls{border:0;padding:0}.pagefind-ui__filter-block.svelte-1v2r7ls.svelte-1v2r7ls{padding:0;display:block;border-bottom:solid calc(2px * var(--pagefind-ui-scale)) var(--pagefind-ui-border);padding:calc(20px * var(--pagefind-ui-scale)) 0}.pagefind-ui__filter-name.svelte-1v2r7ls.svelte-1v2r7ls{font-size:calc(16px * var(--pagefind-ui-scale));position:relative;display:flex;align-items:center;list-style:none;font-weight:700;cursor:pointer;height:calc(24px * var(--pagefind-ui-scale))}.pagefind-ui__filter-name.svelte-1v2r7ls.svelte-1v2r7ls::-webkit-details-marker{display:none}.pagefind-ui__filter-name.svelte-1v2r7ls.svelte-1v2r7ls:after{position:absolute;content:"";right:calc(6px * var(--pagefind-ui-scale));top:50%;width:calc(8px * var(--pagefind-ui-scale));height:calc(8px * var(--pagefind-ui-scale));border:solid calc(2px * var(--pagefind-ui-scale)) currentColor;border-right:0;border-top:0;transform:translateY(-70%) rotate(-45deg)}.pagefind-ui__filter-block[open].svelte-1v2r7ls .pagefind-ui__filter-name.svelte-1v2r7ls:after{transform:translateY(-70%) rotate(-225deg)}.pagefind-ui__filter-group.svelte-1v2r7ls.svelte-1v2r7ls{display:flex;flex-direction:column;gap:calc(20px * var(--pagefind-ui-scale));padding-top:calc(30px * var(--pagefind-ui-scale))}.pagefind-ui__filter-value.svelte-1v2r7ls.svelte-1v2r7ls{position:relative;display:flex;align-items:center;gap:calc(8px * var(--pagefind-ui-scale))}.pagefind-ui__filter-value.svelte-1v2r7ls.svelte-1v2r7ls:before{position:absolute;content:"";top:50%;left:calc(8px * var(--pagefind-ui-scale));width:0px;height:0px;border:solid 1px #fff;opacity:0;transform:translate(calc(4.5px * var(--pagefind-ui-scale) * -1),calc(.8px * var(--pagefind-ui-scale))) skew(-5deg) rotate(-45deg);transform-origin:top left;border-top:0;border-right:0;pointer-events:none}.pagefind-ui__filter-value.pagefind-ui__filter-value--checked.svelte-1v2r7ls.svelte-1v2r7ls:before{opacity:1;width:calc(9px * var(--pagefind-ui-scale));height:calc(4px * var(--pagefind-ui-scale));transition:width .1s ease-out .1s,height .1s ease-in}.pagefind-ui__filter-checkbox.svelte-1v2r7ls.svelte-1v2r7ls{margin:0;width:calc(16px * var(--pagefind-ui-scale));height:calc(16px * var(--pagefind-ui-scale));border:solid 1px var(--pagefind-ui-border);appearance:none;-webkit-appearance:none;border-radius:calc(var(--pagefind-ui-border-radius) / 2);background-color:var(--pagefind-ui-background);cursor:pointer}.pagefind-ui__filter-checkbox.svelte-1v2r7ls.svelte-1v2r7ls:checked{background-color:var(--pagefind-ui-primary);border:solid 1px var(--pagefind-ui-primary)}.pagefind-ui__filter-label.svelte-1v2r7ls.svelte-1v2r7ls{cursor:pointer;font-size:calc(16px * var(--pagefind-ui-scale));font-weight:400}.pagefind-ui--reset *:where(:not(html,iframe,canvas,img,svg,video):not(svg *,symbol *)){all:unset;display:revert;outline:revert}.pagefind-ui--reset *,.pagefind-ui--reset *:before,.pagefind-ui--reset *:after{box-sizing:border-box}.pagefind-ui--reset a,.pagefind-ui--reset button{cursor:revert}.pagefind-ui--reset ol,.pagefind-ui--reset ul,.pagefind-ui--reset menu{list-style:none}.pagefind-ui--reset img{max-width:100%}.pagefind-ui--reset table{border-collapse:collapse}.pagefind-ui--reset input,.pagefind-ui--reset textarea{-webkit-user-select:auto}.pagefind-ui--reset textarea{white-space:revert}.pagefind-ui--reset meter{-webkit-appearance:revert;appearance:revert}.pagefind-ui--reset ::placeholder{color:unset}.pagefind-ui--reset :where([hidden]){display:none}.pagefind-ui--reset :where([contenteditable]:not([contenteditable="false"])){-moz-user-modify:read-write;-webkit-user-modify:read-write;overflow-wrap:break-word;-webkit-line-break:after-white-space;-webkit-user-select:auto}.pagefind-ui--reset :where([draggable="true"]){-webkit-user-drag:element}.pagefind-ui--reset mark{all:revert}:root{--pagefind-ui-scale:.8;--pagefind-ui-primary:#393939;--pagefind-ui-text:#393939;--pagefind-ui-background:#ffffff;--pagefind-ui-border:#eeeeee;--pagefind-ui-tag:#eeeeee;--pagefind-ui-border-width:2px;--pagefind-ui-border-radius:8px;--pagefind-ui-image-border-radius:8px;--pagefind-ui-image-box-ratio:3 / 2;--pagefind-ui-font:system, -apple-system, "BlinkMacSystemFont", ".SFNSText-Regular", "San Francisco", "Roboto", "Segoe UI", "Helvetica Neue", "Lucida Grande", "Ubuntu", "arial", sans-serif}.pagefind-ui.svelte-e9gkc3{width:100%;color:var(--pagefind-ui-text);font-family:var(--pagefind-ui-font)}.pagefind-ui__hidden.svelte-e9gkc3{display:none!important}.pagefind-ui__suppressed.svelte-e9gkc3{opacity:0;pointer-events:none}.pagefind-ui__form.svelte-e9gkc3{position:relative}.pagefind-ui__form.svelte-e9gkc3:before{background-color:var(--pagefind-ui-text);width:calc(18px * var(--pagefind-ui-scale));height:calc(18px * var(--pagefind-ui-scale));top:calc(23px * var(--pagefind-ui-scale));left:calc(20px * var(--pagefind-ui-scale));content:"";position:absolute;display:block;opacity:.7;-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A");mask-image:url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A");-webkit-mask-size:100%;mask-size:100%;z-index:9;pointer-events:none}.pagefind-ui__search-input.svelte-e9gkc3{height:calc(64px * var(--pagefind-ui-scale));padding:0 calc(70px * var(--pagefind-ui-scale)) 0 calc(54px * var(--pagefind-ui-scale));background-color:var(--pagefind-ui-background);border:var(--pagefind-ui-border-width) solid var(--pagefind-ui-border);border-radius:var(--pagefind-ui-border-radius);font-size:calc(21px * var(--pagefind-ui-scale));position:relative;appearance:none;-webkit-appearance:none;display:flex;width:100%;box-sizing:border-box;font-weight:700}.pagefind-ui__search-input.svelte-e9gkc3::placeholder{opacity:.2}.pagefind-ui__search-clear.svelte-e9gkc3{position:absolute;top:calc(3px * var(--pagefind-ui-scale));right:calc(3px * var(--pagefind-ui-scale));height:calc(58px * var(--pagefind-ui-scale));padding:0 calc(15px * var(--pagefind-ui-scale)) 0 calc(2px * var(--pagefind-ui-scale));color:var(--pagefind-ui-text);font-size:calc(14px * var(--pagefind-ui-scale));cursor:pointer;background-color:var(--pagefind-ui-background);border-radius:var(--pagefind-ui-border-radius)}.pagefind-ui__drawer.svelte-e9gkc3{gap:calc(60px * var(--pagefind-ui-scale));display:flex;flex-direction:row;flex-wrap:wrap}.pagefind-ui__results-area.svelte-e9gkc3{min-width:min(calc(400px * var(--pagefind-ui-scale)),100%);flex:1000;margin-top:calc(20px * var(--pagefind-ui-scale))}.pagefind-ui__results.svelte-e9gkc3{padding:0}.pagefind-ui__message.svelte-e9gkc3{box-sizing:content-box;font-size:calc(16px * var(--pagefind-ui-scale));height:calc(24px * var(--pagefind-ui-scale));padding:calc(20px * var(--pagefind-ui-scale)) 0;display:flex;align-items:center;font-weight:700;margin-top:0}.pagefind-ui__button.svelte-e9gkc3{margin-top:calc(40px * var(--pagefind-ui-scale));border:var(--pagefind-ui-border-width) solid var(--pagefind-ui-border);border-radius:var(--pagefind-ui-border-radius);height:calc(48px * var(--pagefind-ui-scale));padding:0 calc(12px * var(--pagefind-ui-scale));font-size:calc(16px * var(--pagefind-ui-scale));color:var(--pagefind-ui-primary);background:var(--pagefind-ui-background);width:100%;text-align:center;font-weight:700;cursor:pointer}.pagefind-ui__button.svelte-e9gkc3:hover{border-color:var(--pagefind-ui-primary);color:var(--pagefind-ui-primary);background:var(--pagefind-ui-background)} diff --git a/public/pagefind/pagefind-ui.js b/public/pagefind/pagefind-ui.js new file mode 100644 index 0000000..d88ad59 --- /dev/null +++ b/public/pagefind/pagefind-ui.js @@ -0,0 +1,2 @@ +(()=>{var Ms=Object.defineProperty;var y=(n,e)=>{for(var t in e)Ms(n,t,{get:e[t],enumerable:!0})};function z(){}function mt(n){return n()}function gn(){return Object.create(null)}function G(n){n.forEach(mt)}function nt(n){return typeof n=="function"}function K(n,e){return n!=n?e==e:n!==e||n&&typeof n=="object"||typeof n=="function"}var et;function ie(n,e){return et||(et=document.createElement("a")),et.href=e,n===et.href}function En(n){return Object.keys(n).length===0}var Rn=typeof window<"u"?window:typeof globalThis<"u"?globalThis:global,de=class{constructor(e){this.options=e,this._listeners="WeakMap"in Rn?new WeakMap:void 0}observe(e,t){return this._listeners.set(e,t),this._getObserver().observe(e,this.options),()=>{this._listeners.delete(e),this._observer.unobserve(e)}}_getObserver(){var e;return(e=this._observer)!==null&&e!==void 0?e:this._observer=new ResizeObserver(t=>{var s;for(let r of t)de.entries.set(r.target,r),(s=this._listeners.get(r.target))===null||s===void 0||s(r)})}};de.entries="WeakMap"in Rn?new WeakMap:void 0;var bn=!1;function As(){bn=!0}function vs(){bn=!1}function b(n,e){n.appendChild(e)}function S(n,e,t){n.insertBefore(e,t||null)}function k(n){n.parentNode&&n.parentNode.removeChild(n)}function Q(n,e){for(let t=0;tn.removeEventListener(e,t,s)}function g(n,e,t){t==null?n.removeAttribute(e):n.getAttribute(e)!==t&&n.setAttribute(e,t)}function Hs(n){return Array.from(n.childNodes)}function N(n,e){e=""+e,n.data!==e&&(n.data=e)}function pt(n,e){n.value=e??""}function B(n,e,t){n.classList[t?"add":"remove"](e)}var st=class{constructor(e=!1){this.is_svg=!1,this.is_svg=e,this.e=this.n=null}c(e){this.h(e)}m(e,t,s=null){this.e||(this.is_svg?this.e=ws(t.nodeName):this.e=C(t.nodeType===11?"TEMPLATE":t.nodeName),this.t=t.tagName!=="TEMPLATE"?t:t.content,this.c(e)),this.i(s)}h(e){this.e.innerHTML=e,this.n=Array.from(this.e.nodeName==="TEMPLATE"?this.e.content.childNodes:this.e.childNodes)}i(e){for(let t=0;tn.indexOf(s)===-1?e.push(s):t.push(s)),t.forEach(s=>s()),re=e}var tt=new Set,ee;function ae(){ee={r:0,c:[],p:ee}}function oe(){ee.r||G(ee.c),ee=ee.p}function U(n,e){n&&n.i&&(tt.delete(n),n.i(e))}function P(n,e,t,s){if(n&&n.o){if(tt.has(n))return;tt.add(n),ee.c.push(()=>{tt.delete(n),s&&(t&&n.d(1),s())}),n.o(e)}else s&&s()}function Sn(n,e){P(n,1,1,()=>{e.delete(n.key)})}function yn(n,e,t,s,r,l,i,a,o,f,u,m){let p=n.length,h=l.length,_=p,c={};for(;_--;)c[n[_].key]=_;let d=[],T=new Map,R=new Map,M=[];for(_=h;_--;){let v=m(r,l,_),H=t(v),O=i.get(H);O?s&&M.push(()=>O.p(v,e)):(O=f(H,v),O.c()),T.set(H,d[_]=O),H in c&&R.set(H,Math.abs(_-c[H]))}let D=new Set,X=new Set;function V(v){U(v,1),v.m(a,u),i.set(v.key,v),u=v.first,h--}for(;p&&h;){let v=d[h-1],H=n[p-1],O=v.key,W=H.key;v===H?(u=v.first,p--,h--):T.has(W)?!i.has(O)||D.has(O)?V(v):X.has(W)?p--:R.get(O)>R.get(W)?(X.add(O),V(v)):(D.add(W),p--):(o(H,i),p--)}for(;p--;){let v=n[p];T.has(v.key)||o(v,i)}for(;h;)V(d[h-1]);return G(M),d}var zs=["allowfullscreen","allowpaymentrequest","async","autofocus","autoplay","checked","controls","default","defer","disabled","formnovalidate","hidden","inert","ismap","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","selected"],Ua=new Set([...zs]);function Mn(n,e,t){let s=n.$$.props[e];s!==void 0&&(n.$$.bound[s]=t,t(n.$$.ctx[s]))}function rt(n){n&&n.c()}function me(n,e,t,s){let{fragment:r,after_update:l}=n.$$;r&&r.m(e,t),s||ht(()=>{let i=n.$$.on_mount.map(mt).filter(nt);n.$$.on_destroy?n.$$.on_destroy.push(...i):G(i),n.$$.on_mount=[]}),l.forEach(ht)}function ue(n,e){let t=n.$$;t.fragment!==null&&(js(t.after_update),G(t.on_destroy),t.fragment&&t.fragment.d(e),t.on_destroy=t.fragment=null,t.ctx=[])}function Us(n,e){n.$$.dirty[0]===-1&&(se.push(n),Ns(),n.$$.dirty.fill(0)),n.$$.dirty[e/31|0]|=1<{let _=h.length?h[0]:p;return f.ctx&&r(f.ctx[m],f.ctx[m]=_)&&(!f.skip_bound&&f.bound[m]&&f.bound[m](_),u&&Us(n,m)),p}):[],f.update(),u=!0,G(f.before_update),f.fragment=s?s(f.ctx):!1,e.target){if(e.hydrate){As();let m=Hs(e.target);f.fragment&&f.fragment.l(m),m.forEach(k)}else f.fragment&&f.fragment.c();e.intro&&U(n.$$.fragment),me(n,e.target,e.anchor,e.customElement),vs(),kn()}fe(o)}var Ds;typeof HTMLElement=="function"&&(Ds=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){let{on_mount:n}=this.$$;this.$$.on_disconnect=n.map(mt).filter(nt);for(let e in this.$$.slotted)this.appendChild(this.$$.slotted[e])}attributeChangedCallback(n,e,t){this[n]=t}disconnectedCallback(){G(this.$$.on_disconnect)}$destroy(){ue(this,1),this.$destroy=z}$on(n,e){if(!nt(e))return z;let t=this.$$.callbacks[n]||(this.$$.callbacks[n]=[]);return t.push(e),()=>{let s=t.indexOf(e);s!==-1&&t.splice(s,1)}}$set(n){this.$$set&&!En(n)&&(this.$$.skip_bound=!0,this.$$set(n),this.$$.skip_bound=!1)}});var q=class{$destroy(){ue(this,1),this.$destroy=z}$on(e,t){if(!nt(t))return z;let s=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return s.push(t),()=>{let r=s.indexOf(t);r!==-1&&s.splice(r,1)}}$set(e){this.$$set&&!En(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}};function I(n){let e=typeof n=="string"?n.charCodeAt(0):n;return e>=97&&e<=122||e>=65&&e<=90}function $(n){let e=typeof n=="string"?n.charCodeAt(0):n;return e>=48&&e<=57}function Z(n){return I(n)||$(n)}var An=["art-lojban","cel-gaulish","no-bok","no-nyn","zh-guoyu","zh-hakka","zh-min","zh-min-nan","zh-xiang"];var Rt={"en-gb-oed":"en-GB-oxendict","i-ami":"ami","i-bnn":"bnn","i-default":null,"i-enochian":null,"i-hak":"hak","i-klingon":"tlh","i-lux":"lb","i-mingo":null,"i-navajo":"nv","i-pwn":"pwn","i-tao":"tao","i-tay":"tay","i-tsu":"tsu","sgn-be-fr":"sfb","sgn-be-nl":"vgt","sgn-ch-de":"sgg","art-lojban":"jbo","cel-gaulish":null,"no-bok":"nb","no-nyn":"nn","zh-guoyu":"cmn","zh-hakka":"hak","zh-min":null,"zh-min-nan":"nan","zh-xiang":"hsn"};var Is={}.hasOwnProperty;function lt(n,e={}){let t=vn(),s=String(n),r=s.toLowerCase(),l=0;if(n==null)throw new Error("Expected string, got `"+n+"`");if(Is.call(Rt,r)){let a=Rt[r];return(e.normalize===void 0||e.normalize===null||e.normalize)&&typeof a=="string"?lt(a):(t[An.includes(r)?"regular":"irregular"]=s,t)}for(;I(r.charCodeAt(l))&&l<9;)l++;if(l>1&&l<9){if(t.language=s.slice(0,l),l<4){let a=0;for(;r.charCodeAt(l)===45&&I(r.charCodeAt(l+1))&&I(r.charCodeAt(l+2))&&I(r.charCodeAt(l+3))&&!I(r.charCodeAt(l+4));){if(a>2)return i(l,3,"Too many extended language subtags, expected at most 3 subtags");t.extendedLanguageSubtags.push(s.slice(l+1,l+4)),l+=4,a++}}for(r.charCodeAt(l)===45&&I(r.charCodeAt(l+1))&&I(r.charCodeAt(l+2))&&I(r.charCodeAt(l+3))&&I(r.charCodeAt(l+4))&&!I(r.charCodeAt(l+5))&&(t.script=s.slice(l+1,l+5),l+=5),r.charCodeAt(l)===45&&(I(r.charCodeAt(l+1))&&I(r.charCodeAt(l+2))&&!I(r.charCodeAt(l+3))?(t.region=s.slice(l+1,l+3),l+=3):$(r.charCodeAt(l+1))&&$(r.charCodeAt(l+2))&&$(r.charCodeAt(l+3))&&!$(r.charCodeAt(l+4))&&(t.region=s.slice(l+1,l+4),l+=4));r.charCodeAt(l)===45;){let a=l+1,o=a;for(;Z(r.charCodeAt(o));){if(o-a>7)return i(o,1,"Too long variant, expected at most 8 characters");o++}if(o-a>4||o-a>3&&$(r.charCodeAt(a)))t.variants.push(s.slice(a,o)),l=o;else break}for(;r.charCodeAt(l)===45&&!(r.charCodeAt(l+1)===120||!Z(r.charCodeAt(l+1))||r.charCodeAt(l+2)!==45||!Z(r.charCodeAt(l+3)));){let a=l+2,o=0;for(;r.charCodeAt(a)===45&&Z(r.charCodeAt(a+1))&&Z(r.charCodeAt(a+2));){let f=a+1;for(a=f+2,o++;Z(r.charCodeAt(a));){if(a-f>7)return i(a,2,"Too long extension, expected at most 8 characters");a++}}if(!o)return i(a,4,"Empty extension, extensions must have at least 2 characters of content");t.extensions.push({singleton:s.charAt(l+1),extensions:s.slice(l+3,a).split("-")}),l=a}}else l=0;if(l===0&&r.charCodeAt(l)===120||r.charCodeAt(l)===45&&r.charCodeAt(l+1)===120){l=l?l+2:1;let a=l;for(;r.charCodeAt(a)===45&&Z(r.charCodeAt(a+1));){let o=l+1;for(a=o;Z(r.charCodeAt(a));){if(a-o>7)return i(a,5,"Too long private-use area, expected at most 8 characters");a++}t.privateuse.push(s.slice(l+1,a)),l=a}}if(l!==s.length)return i(l,6,"Found superfluous content after tag");return t;function i(a,o,f){return e.warning&&e.warning(f,o,a),e.forgiving?t:vn()}}function vn(){return{language:null,extendedLanguageSubtags:[],script:null,region:null,variants:[],extensions:[],privateuse:[],irregular:null,regular:null}}function wn(n,e,t){let s=n.slice();return s[8]=e[t][0],s[9]=e[t][1],s}function Ps(n){let e,t,s,r,l,i=n[0]&&Hn(n);return{c(){i&&i.c(),e=A(),t=C("div"),s=C("p"),s.textContent=`${n[3](30)}`,r=A(),l=C("p"),l.textContent=`${n[3](40)}`,g(s,"class","pagefind-ui__result-title pagefind-ui__loading svelte-j9e30"),g(l,"class","pagefind-ui__result-excerpt pagefind-ui__loading svelte-j9e30"),g(t,"class","pagefind-ui__result-inner svelte-j9e30")},m(a,o){i&&i.m(a,o),S(a,e,o),S(a,t,o),b(t,s),b(t,r),b(t,l)},p(a,o){a[0]?i||(i=Hn(a),i.c(),i.m(e.parentNode,e)):i&&(i.d(1),i=null)},d(a){i&&i.d(a),a&&k(e),a&&k(t)}}}function Ls(n){let e,t,s,r,l=n[1].meta?.title+"",i,a,o,f,u=n[1].excerpt+"",m,p=n[0]&&Fn(n),h=n[2].length&&On(n);return{c(){p&&p.c(),e=A(),t=C("div"),s=C("p"),r=C("a"),i=w(l),o=A(),f=C("p"),m=A(),h&&h.c(),g(r,"class","pagefind-ui__result-link svelte-j9e30"),g(r,"href",a=n[1].meta?.url||n[1].url),g(s,"class","pagefind-ui__result-title svelte-j9e30"),g(f,"class","pagefind-ui__result-excerpt svelte-j9e30"),g(t,"class","pagefind-ui__result-inner svelte-j9e30")},m(_,c){p&&p.m(_,c),S(_,e,c),S(_,t,c),b(t,s),b(s,r),b(r,i),b(t,o),b(t,f),f.innerHTML=u,b(t,m),h&&h.m(t,null)},p(_,c){_[0]?p?p.p(_,c):(p=Fn(_),p.c(),p.m(e.parentNode,e)):p&&(p.d(1),p=null),c&2&&l!==(l=_[1].meta?.title+"")&&N(i,l),c&2&&a!==(a=_[1].meta?.url||_[1].url)&&g(r,"href",a),c&2&&u!==(u=_[1].excerpt+"")&&(f.innerHTML=u),_[2].length?h?h.p(_,c):(h=On(_),h.c(),h.m(t,null)):h&&(h.d(1),h=null)},d(_){p&&p.d(_),_&&k(e),_&&k(t),h&&h.d()}}}function Hn(n){let e;return{c(){e=C("div"),g(e,"class","pagefind-ui__result-thumb pagefind-ui__loading svelte-j9e30")},m(t,s){S(t,e,s)},d(t){t&&k(e)}}}function Fn(n){let e,t=n[1].meta.image&&Nn(n);return{c(){e=C("div"),t&&t.c(),g(e,"class","pagefind-ui__result-thumb svelte-j9e30")},m(s,r){S(s,e,r),t&&t.m(e,null)},p(s,r){s[1].meta.image?t?t.p(s,r):(t=Nn(s),t.c(),t.m(e,null)):t&&(t.d(1),t=null)},d(s){s&&k(e),t&&t.d()}}}function Nn(n){let e,t,s;return{c(){e=C("img"),g(e,"class","pagefind-ui__result-image svelte-j9e30"),ie(e.src,t=n[1].meta?.image)||g(e,"src",t),g(e,"alt",s=n[1].meta?.image_alt||n[1].meta?.title)},m(r,l){S(r,e,l)},p(r,l){l&2&&!ie(e.src,t=r[1].meta?.image)&&g(e,"src",t),l&2&&s!==(s=r[1].meta?.image_alt||r[1].meta?.title)&&g(e,"alt",s)},d(r){r&&k(e)}}}function On(n){let e,t=n[2],s=[];for(let r=0;rn.toLocaleUpperCase();function Bs(n,e,t){let{show_images:s=!0}=e,{process_result:r=null}=e,{result:l={data:async()=>{}}}=e,i=["title","image","image_alt","url"],a,o=[],f=async m=>{t(1,a=await m.data()),t(1,a=r?.(a)??a),t(2,o=Object.entries(a.meta).filter(([p])=>!i.includes(p)))},u=(m=30)=>". ".repeat(Math.floor(10+Math.random()*m));return n.$$set=m=>{"show_images"in m&&t(0,s=m.show_images),"process_result"in m&&t(4,r=m.process_result),"result"in m&&t(5,l=m.result)},n.$$.update=()=>{if(n.$$.dirty&32)e:f(l)},[s,a,o,u,r,l]}var bt=class extends q{constructor(e){super(),Y(this,e,Bs,qs,K,{show_images:0,process_result:4,result:5})}},Un=bt;function Dn(n,e,t){let s=n.slice();return s[11]=e[t][0],s[12]=e[t][1],s}function In(n,e,t){let s=n.slice();return s[15]=e[t],s}function Vs(n){let e,t,s,r,l,i=n[0]&&Pn(n);return{c(){i&&i.c(),e=A(),t=C("div"),s=C("p"),s.textContent=`${n[5](30)}`,r=A(),l=C("p"),l.textContent=`${n[5](40)}`,g(s,"class","pagefind-ui__result-title pagefind-ui__loading svelte-4xnkmf"),g(l,"class","pagefind-ui__result-excerpt pagefind-ui__loading svelte-4xnkmf"),g(t,"class","pagefind-ui__result-inner svelte-4xnkmf")},m(a,o){i&&i.m(a,o),S(a,e,o),S(a,t,o),b(t,s),b(t,r),b(t,l)},p(a,o){a[0]?i||(i=Pn(a),i.c(),i.m(e.parentNode,e)):i&&(i.d(1),i=null)},d(a){i&&i.d(a),a&&k(e),a&&k(t)}}}function Ws(n){let e,t,s,r,l=n[1].meta?.title+"",i,a,o,f,u,m=n[0]&&Ln(n),p=n[4]&&Bn(n),h=n[3],_=[];for(let d=0;dn.toLocaleUpperCase();function Ks(n,e,t){let{show_images:s=!0}=e,{process_result:r=null}=e,{result:l={data:async()=>{}}}=e,i=["title","image","image_alt","url"],a,o=[],f=[],u=!1,m=(_,c)=>{if(_.length<=c)return _;let d=[..._].sort((T,R)=>R.locations.length-T.locations.length).slice(0,3).map(T=>T.url);return _.filter(T=>d.includes(T.url))},p=async _=>{t(1,a=await _.data()),t(1,a=r?.(a)??a),t(2,o=Object.entries(a.meta).filter(([c])=>!i.includes(c))),Array.isArray(a.sub_results)&&(t(4,u=a.sub_results?.[0]?.url===(a.meta?.url||a.url)),u?t(3,f=m(a.sub_results.slice(1),3)):t(3,f=m([...a.sub_results],3)))},h=(_=30)=>". ".repeat(Math.floor(10+Math.random()*_));return n.$$set=_=>{"show_images"in _&&t(0,s=_.show_images),"process_result"in _&&t(6,r=_.process_result),"result"in _&&t(7,l=_.result)},n.$$.update=()=>{if(n.$$.dirty&128)e:p(l)},[s,a,o,f,u,h,r,l]}var Tt=class extends q{constructor(e){super(),Y(this,e,Ks,Gs,K,{show_images:0,process_result:6,result:7})}},Jn=Tt;function Yn(n,e,t){let s=n.slice();return s[10]=e[t][0],s[11]=e[t][1],s[12]=e,s[13]=t,s}function Zn(n,e,t){let s=n.slice();return s[14]=e[t][0],s[15]=e[t][1],s[16]=e,s[17]=t,s}function Xn(n){let e,t,s=n[4]("filters_label",n[5],n[6])+"",r,l,i=Object.entries(n[1]),a=[];for(let o=0;on.toLocaleUpperCase(),ts=n=>n.toLowerCase();function Ys(n,e,t){let{available_filters:s=null}=e,{show_empty_filters:r=!0}=e,{open_filters:l=[]}=e,{translate:i=()=>""}=e,{automatic_translations:a={}}=e,{translations:o={}}=e,{selected_filters:f={}}=e,u=!1,m=!1;function p(h,_){f[`${h}:${_}`]=this.checked,t(0,f)}return n.$$set=h=>{"available_filters"in h&&t(1,s=h.available_filters),"show_empty_filters"in h&&t(2,r=h.show_empty_filters),"open_filters"in h&&t(3,l=h.open_filters),"translate"in h&&t(4,i=h.translate),"automatic_translations"in h&&t(5,a=h.automatic_translations),"translations"in h&&t(6,o=h.translations),"selected_filters"in h&&t(0,f=h.selected_filters)},n.$$.update=()=>{if(n.$$.dirty&258){e:if(s&&!u){t(8,u=!0);let h=Object.entries(s||{});h.length===1&&Object.entries(h[0][1])?.length<=6&&t(7,m=!0)}}},[f,s,r,l,i,a,o,m,u,p]}var Ct=class extends q{constructor(e){super(),Y(this,e,Ys,Js,K,{available_filters:1,show_empty_filters:2,open_filters:3,translate:4,automatic_translations:5,translations:6,selected_filters:0})}},ns=Ct;var kt={};y(kt,{comments:()=>Xs,default:()=>$s,direction:()=>Qs,strings:()=>xs,thanks_to:()=>Zs});var Zs="Jan Claasen ",Xs="",Qs="ltr",xs={placeholder:"Soek",clear_search:"Opruim",load_more:"Laai nog resultate",search_label:"Soek hierdie webwerf",filters_label:"Filters",zero_results:"Geen resultate vir [SEARCH_TERM]",many_results:"[COUNT] resultate vir [SEARCH_TERM]",one_result:"[COUNT] resultate vir [SEARCH_TERM]",alt_search:"Geen resultate vir [SEARCH_TERM]. Toon resultate vir [DIFFERENT_TERM] in plaas daarvan",search_suggestion:"Geen resultate vir [SEARCH_TERM]. Probeer eerder een van die volgende terme:",searching:"Soek vir [SEARCH_TERM]"},$s={thanks_to:Zs,comments:Xs,direction:Qs,strings:xs};var St={};y(St,{comments:()=>tr,default:()=>rr,direction:()=>nr,strings:()=>sr,thanks_to:()=>er});var er="Jermanuts",tr="",nr="rtl",sr={placeholder:"\u0628\u062D\u062B",clear_search:"\u0627\u0645\u0633\u062D",load_more:"\u062D\u0645\u0651\u0650\u0644 \u0627\u0644\u0645\u0632\u064A\u062F \u0645\u0646 \u0627\u0644\u0646\u062A\u0627\u0626\u062C",search_label:"\u0627\u0628\u062D\u062B \u0641\u064A \u0647\u0630\u0627 \u0627\u0644\u0645\u0648\u0642\u0639",filters_label:"\u062A\u0635\u0641\u064A\u0627\u062A",zero_results:"\u0644\u0627 \u062A\u0648\u062C\u062F \u0646\u062A\u0627\u0626\u062C \u0644 [SEARCH_TERM]",many_results:"[COUNT] \u0646\u062A\u0627\u0626\u062C \u0644 [SEARCH_TERM]",one_result:"[COUNT] \u0646\u062A\u064A\u062C\u0629 \u0644 [SEARCH_TERM]",alt_search:"\u0644\u0627 \u062A\u0648\u062C\u062F \u0646\u062A\u0627\u0626\u062C \u0644 [SEARCH_TERM]. \u064A\u0639\u0631\u0636 \u0627\u0644\u0646\u062A\u0627\u0626\u062C \u0644 [DIFFERENT_TERM] \u0628\u062F\u0644\u0627\u064B \u0645\u0646 \u0630\u0644\u0643",search_suggestion:"\u0644\u0627 \u062A\u0648\u062C\u062F \u0646\u062A\u0627\u0626\u062C \u0644 [SEARCH_TERM]. \u062C\u0631\u0628 \u0623\u062D\u062F \u0639\u0645\u0644\u064A\u0627\u062A \u0627\u0644\u0628\u062D\u062B \u0627\u0644\u062A\u0627\u0644\u064A\u0629:",searching:"\u064A\u0628\u062D\u062B \u0639\u0646 [SEARCH_TERM]..."},rr={thanks_to:er,comments:tr,direction:nr,strings:sr};var yt={};y(yt,{comments:()=>ir,default:()=>ur,direction:()=>ar,strings:()=>or,thanks_to:()=>lr});var lr="Maruf Alom ",ir="",ar="ltr",or={placeholder:"\u0985\u09A8\u09C1\u09B8\u09A8\u09CD\u09A7\u09BE\u09A8 \u0995\u09B0\u09C1\u09A8",clear_search:"\u09AE\u09C1\u099B\u09C7 \u09AB\u09C7\u09B2\u09C1\u09A8",load_more:"\u0986\u09B0\u09CB \u09AB\u09B2\u09BE\u09AB\u09B2 \u09A6\u09C7\u0996\u09C1\u09A8",search_label:"\u098F\u0987 \u0993\u09DF\u09C7\u09AC\u09B8\u09BE\u0987\u099F\u09C7 \u0985\u09A8\u09C1\u09B8\u09A8\u09CD\u09A7\u09BE\u09A8 \u0995\u09B0\u09C1\u09A8",filters_label:"\u09AB\u09BF\u09B2\u09CD\u099F\u09BE\u09B0",zero_results:"[SEARCH_TERM] \u098F\u09B0 \u099C\u09A8\u09CD\u09AF \u0995\u09BF\u099B\u09C1 \u0996\u09C1\u0981\u099C\u09C7 \u09AA\u09BE\u0993\u09DF\u09BE \u09AF\u09BE\u09DF\u09A8\u09BF",many_results:"[COUNT]-\u099F\u09BF \u09AB\u09B2\u09BE\u09AB\u09B2 \u09AA\u09BE\u0993\u09DF\u09BE \u0997\u09BF\u09DF\u09C7\u099B\u09C7 [SEARCH_TERM] \u098F\u09B0 \u099C\u09A8\u09CD\u09AF",one_result:"[COUNT]-\u099F\u09BF \u09AB\u09B2\u09BE\u09AB\u09B2 \u09AA\u09BE\u0993\u09DF\u09BE \u0997\u09BF\u09DF\u09C7\u099B\u09C7 [SEARCH_TERM] \u098F\u09B0 \u099C\u09A8\u09CD\u09AF",alt_search:"\u0995\u09CB\u09A8 \u0995\u09BF\u099B\u09C1 \u0996\u09C1\u0981\u099C\u09C7 \u09AA\u09BE\u0993\u09DF\u09BE \u09AF\u09BE\u09DF\u09A8\u09BF [SEARCH_TERM] \u098F\u09B0 \u099C\u09A8\u09CD\u09AF. \u09AA\u09B0\u09BF\u09AC\u09B0\u09CD\u09A4\u09C7 [DIFFERENT_TERM] \u098F\u09B0 \u099C\u09A8\u09CD\u09AF \u09A6\u09C7\u0996\u09BE\u09A8\u09CB \u09B9\u099A\u09CD\u099B\u09C7",search_suggestion:"\u0995\u09CB\u09A8 \u0995\u09BF\u099B\u09C1 \u0996\u09C1\u0981\u099C\u09C7 \u09AA\u09BE\u0993\u09DF\u09BE \u09AF\u09BE\u09DF\u09A8\u09BF [SEARCH_TERM] \u098F\u09B0 \u09AC\u09BF\u09B7\u09DF\u09C7. \u09A8\u09BF\u09A8\u09CD\u09AE\u09C7\u09B0 \u09AC\u09BF\u09B7\u09DF\u09AC\u09B8\u09CD\u09A4\u09C1 \u0996\u09C1\u0981\u099C\u09C7 \u09A6\u09C7\u0996\u09C1\u09A8:",searching:"\u0985\u09A8\u09C1\u09B8\u09A8\u09CD\u09A7\u09BE\u09A8 \u099A\u09B2\u099B\u09C7 [SEARCH_TERM]..."},ur={thanks_to:lr,comments:ir,direction:ar,strings:or};var Mt={};y(Mt,{comments:()=>_r,default:()=>hr,direction:()=>fr,strings:()=>dr,thanks_to:()=>cr});var cr="Pablo Villaverde ",_r="",fr="ltr",dr={placeholder:"Cerca",clear_search:"Netejar",load_more:"Veure m\xE9s resultats",search_label:"Cerca en aquest lloc",filters_label:"Filtres",zero_results:"No es van trobar resultats per [SEARCH_TERM]",many_results:"[COUNT] resultats trobats per [SEARCH_TERM]",one_result:"[COUNT] resultat trobat per [SEARCH_TERM]",alt_search:"No es van trobar resultats per [SEARCH_TERM]. Mostrant al seu lloc resultats per [DIFFERENT_TERM]",search_suggestion:"No es van trobar resultats per [SEARCH_TERM]. Proveu una de les cerques seg\xFCents:",searching:"Cercant [SEARCH_TERM]..."},hr={thanks_to:cr,comments:_r,direction:fr,strings:dr};var At={};y(At,{comments:()=>pr,default:()=>Rr,direction:()=>gr,strings:()=>Er,thanks_to:()=>mr});var mr="Dalibor Hon ",pr="",gr="ltr",Er={placeholder:"Hledat",clear_search:"Smazat",load_more:"Na\u010D\xEDst dal\u0161\xED v\xFDsledky",search_label:"Prohledat tuto str\xE1nku",filters_label:"Filtry",zero_results:"\u017D\xE1dn\xE9 v\xFDsledky pro [SEARCH_TERM]",many_results:"[COUNT] v\xFDsledk\u016F pro [SEARCH_TERM]",one_result:"[COUNT] v\xFDsledek pro [SEARCH_TERM]",alt_search:"\u017D\xE1dn\xE9 v\xFDsledky pro [SEARCH_TERM]. Zobrazuj\xED se v\xFDsledky pro [DIFFERENT_TERM]",search_suggestion:"\u017D\xE1dn\xE9 v\xFDsledky pro [SEARCH_TERM]. Souvisej\xEDc\xED v\xFDsledky hled\xE1n\xED:",searching:"Hled\xE1m [SEARCH_TERM]..."},Rr={thanks_to:mr,comments:pr,direction:gr,strings:Er};var vt={};y(vt,{comments:()=>Tr,default:()=>Sr,direction:()=>Cr,strings:()=>kr,thanks_to:()=>br});var br="Jonas Smedegaard ",Tr="",Cr="ltr",kr={placeholder:"S\xF8g",clear_search:"Nulstil",load_more:"Indl\xE6s flere resultater",search_label:"S\xF8g p\xE5 dette website",filters_label:"Filtre",zero_results:"Ingen resultater for [SEARCH_TERM]",many_results:"[COUNT] resultater for [SEARCH_TERM]",one_result:"[COUNT] resultat for [SEARCH_TERM]",alt_search:"Ingen resultater for [SEARCH_TERM]. Viser resultater for [DIFFERENT_TERM] i stedet",search_suggestion:"Ingen resultater for [SEARCH_TERM]. Pr\xF8v et af disse s\xF8geord i stedet:",searching:"S\xF8ger efter [SEARCH_TERM]..."},Sr={thanks_to:br,comments:Tr,direction:Cr,strings:kr};var wt={};y(wt,{comments:()=>Mr,default:()=>wr,direction:()=>Ar,strings:()=>vr,thanks_to:()=>yr});var yr="Jan Claasen ",Mr="",Ar="ltr",vr={placeholder:"Suche",clear_search:"L\xF6schen",load_more:"Mehr Ergebnisse laden",search_label:"Suche diese Seite",filters_label:"Filter",zero_results:"Keine Ergebnisse f\xFCr [SEARCH_TERM]",many_results:"[COUNT] Ergebnisse f\xFCr [SEARCH_TERM]",one_result:"[COUNT] Ergebnis f\xFCr [SEARCH_TERM]",alt_search:"Keine Ergebnisse f\xFCr [SEARCH_TERM]. Stattdessen werden Ergebnisse f\xFCr [DIFFERENT_TERM] angezeigt",search_suggestion:"Keine Ergebnisse f\xFCr [SEARCH_TERM]. Versuchen Sie eine der folgenden Suchen:",searching:"Suche f\xFCr [SEARCH_TERM]"},wr={thanks_to:yr,comments:Mr,direction:Ar,strings:vr};var Ht={};y(Ht,{comments:()=>Fr,default:()=>jr,direction:()=>Nr,strings:()=>Or,thanks_to:()=>Hr});var Hr="Liam Bigelow ",Fr="",Nr="ltr",Or={placeholder:"Search",clear_search:"Clear",load_more:"Load more results",search_label:"Search this site",filters_label:"Filters",zero_results:"No results for [SEARCH_TERM]",many_results:"[COUNT] results for [SEARCH_TERM]",one_result:"[COUNT] result for [SEARCH_TERM]",alt_search:"No results for [SEARCH_TERM]. Showing results for [DIFFERENT_TERM] instead",search_suggestion:"No results for [SEARCH_TERM]. Try one of the following searches:",searching:"Searching for [SEARCH_TERM]..."},jr={thanks_to:Hr,comments:Fr,direction:Nr,strings:Or};var Ft={};y(Ft,{comments:()=>Ur,default:()=>Pr,direction:()=>Dr,strings:()=>Ir,thanks_to:()=>zr});var zr="Pablo Villaverde ",Ur="",Dr="ltr",Ir={placeholder:"Buscar",clear_search:"Limpiar",load_more:"Ver m\xE1s resultados",search_label:"Buscar en este sitio",filters_label:"Filtros",zero_results:"No se encontraron resultados para [SEARCH_TERM]",many_results:"[COUNT] resultados encontrados para [SEARCH_TERM]",one_result:"[COUNT] resultado encontrado para [SEARCH_TERM]",alt_search:"No se encontraron resultados para [SEARCH_TERM]. Mostrando en su lugar resultados para [DIFFERENT_TERM]",search_suggestion:"No se encontraron resultados para [SEARCH_TERM]. Prueba una de las siguientes b\xFAsquedas:",searching:"Buscando [SEARCH_TERM]..."},Pr={thanks_to:zr,comments:Ur,direction:Dr,strings:Ir};var Nt={};y(Nt,{comments:()=>qr,default:()=>Wr,direction:()=>Br,strings:()=>Vr,thanks_to:()=>Lr});var Lr="Ali Khaleqi Yekta ",qr="",Br="rtl",Vr={placeholder:"\u062C\u0633\u062A\u062C\u0648",clear_search:"\u067E\u0627\u06A9\u0633\u0627\u0632\u06CC",load_more:"\u0628\u0627\u0631\u06AF\u0630\u0627\u0631\u06CC \u0646\u062A\u0627\u06CC\u062C \u0628\u06CC\u0634\u062A\u0631",search_label:"\u062C\u0633\u062A\u062C\u0648 \u062F\u0631 \u0633\u0627\u06CC\u062A",filters_label:"\u0641\u06CC\u0644\u062A\u0631\u0647\u0627",zero_results:"\u0646\u062A\u06CC\u062C\u0647\u200C\u0627\u06CC \u0628\u0631\u0627\u06CC [SEARCH_TERM] \u06CC\u0627\u0641\u062A \u0646\u0634\u062F",many_results:"[COUNT] \u0646\u062A\u06CC\u062C\u0647 \u0628\u0631\u0627\u06CC [SEARCH_TERM] \u06CC\u0627\u0641\u062A \u0634\u062F",one_result:"[COUNT] \u0646\u062A\u06CC\u062C\u0647 \u0628\u0631\u0627\u06CC [SEARCH_TERM] \u06CC\u0627\u0641\u062A \u0634\u062F",alt_search:"\u0646\u062A\u06CC\u062C\u0647\u200C\u0627\u06CC \u0628\u0631\u0627\u06CC [SEARCH_TERM] \u06CC\u0627\u0641\u062A \u0646\u0634\u062F. \u062F\u0631 \u0639\u0648\u0636 \u0646\u062A\u0627\u06CC\u062C \u0628\u0631\u0627\u06CC [DIFFERENT_TERM] \u0646\u0645\u0627\u06CC\u0634 \u062F\u0627\u062F\u0647 \u0645\u06CC\u200C\u0634\u0648\u062F",search_suggestion:"\u0646\u062A\u06CC\u062C\u0647\u200C\u0627\u06CC \u0628\u0631\u0627\u06CC [SEARCH_TERM] \u06CC\u0627\u0641\u062A \u0646\u0634\u062F. \u06CC\u06A9\u06CC \u0627\u0632 \u062C\u0633\u062A\u062C\u0648\u0647\u0627\u06CC \u0632\u06CC\u0631 \u0631\u0627 \u0627\u0645\u062A\u062D\u0627\u0646 \u06A9\u0646\u06CC\u062F:",searching:"\u062F\u0631 \u062D\u0627\u0644 \u062C\u0633\u062A\u062C\u0648\u06CC [SEARCH_TERM]..."},Wr={thanks_to:Lr,comments:qr,direction:Br,strings:Vr};var Ot={};y(Ot,{comments:()=>Kr,default:()=>Zr,direction:()=>Jr,strings:()=>Yr,thanks_to:()=>Gr});var Gr="Valtteri Laitinen ",Kr="",Jr="ltr",Yr={placeholder:"Haku",clear_search:"Tyhjenn\xE4",load_more:"Lataa lis\xE4\xE4 tuloksia",search_label:"Hae t\xE4lt\xE4 sivustolta",filters_label:"Suodattimet",zero_results:"Ei tuloksia haulle [SEARCH_TERM]",many_results:"[COUNT] tulosta haulle [SEARCH_TERM]",one_result:"[COUNT] tulos haulle [SEARCH_TERM]",alt_search:"Ei tuloksia haulle [SEARCH_TERM]. N\xE4ytet\xE4\xE4n tulokset sen sijaan haulle [DIFFERENT_TERM]",search_suggestion:"Ei tuloksia haulle [SEARCH_TERM]. Kokeile jotain seuraavista:",searching:"Haetaan [SEARCH_TERM]..."},Zr={thanks_to:Gr,comments:Kr,direction:Jr,strings:Yr};var jt={};y(jt,{comments:()=>Qr,default:()=>el,direction:()=>xr,strings:()=>$r,thanks_to:()=>Xr});var Xr="Nicolas Friedli ",Qr="",xr="ltr",$r={placeholder:"Rechercher",clear_search:"Nettoyer",load_more:"Charger plus de r\xE9sultats",search_label:"Recherche sur ce site",filters_label:"Filtres",zero_results:"Pas de r\xE9sultat pour [SEARCH_TERM]",many_results:"[COUNT] r\xE9sultats pour [SEARCH_TERM]",one_result:"[COUNT] r\xE9sultat pour [SEARCH_TERM]",alt_search:"Pas de r\xE9sultat pour [SEARCH_TERM]. Montre les r\xE9sultats pour [DIFFERENT_TERM] \xE0 la place",search_suggestion:"Pas de r\xE9sultat pour [SEARCH_TERM]. Essayer une des recherches suivantes:",searching:"Recherche [SEARCH_TERM]..."},el={thanks_to:Xr,comments:Qr,direction:xr,strings:$r};var zt={};y(zt,{comments:()=>nl,default:()=>ll,direction:()=>sl,strings:()=>rl,thanks_to:()=>tl});var tl="Pablo Villaverde ",nl="",sl="ltr",rl={placeholder:"Buscar",clear_search:"Limpar",load_more:"Ver m\xE1is resultados",search_label:"Buscar neste sitio",filters_label:"Filtros",zero_results:"Non se atoparon resultados para [SEARCH_TERM]",many_results:"[COUNT] resultados atopados para [SEARCH_TERM]",one_result:"[COUNT] resultado atopado para [SEARCH_TERM]",alt_search:"Non se atoparon resultados para [SEARCH_TERM]. Amosando no seu lugar resultados para [DIFFERENT_TERM]",search_suggestion:"Non se atoparon resultados para [SEARCH_TERM]. Probe unha das seguintes pesquisas:",searching:"Buscando [SEARCH_TERM]..."},ll={thanks_to:tl,comments:nl,direction:sl,strings:rl};var Ut={};y(Ut,{comments:()=>al,default:()=>cl,direction:()=>ol,strings:()=>ul,thanks_to:()=>il});var il="Nir Tamir ",al="",ol="rtl",ul={placeholder:"\u05D7\u05D9\u05E4\u05D5\u05E9",clear_search:"\u05E0\u05D9\u05E7\u05D5\u05D9",load_more:"\u05E2\u05D5\u05D3 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA",search_label:"\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D1\u05D0\u05EA\u05E8 \u05D6\u05D4",filters_label:"\u05DE\u05E1\u05E0\u05E0\u05D9\u05DD",zero_results:"\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA \u05E2\u05D1\u05D5\u05E8 [SEARCH_TERM]",many_results:"\u05E0\u05DE\u05E6\u05D0\u05D5 [COUNT] \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA \u05E2\u05D1\u05D5\u05E8 [SEARCH_TERM]",one_result:"\u05E0\u05DE\u05E6\u05D0\u05D4 \u05EA\u05D5\u05E6\u05D0\u05D4 \u05D0\u05D7\u05EA \u05E2\u05D1\u05D5\u05E8 [SEARCH_TERM]",alt_search:"\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA \u05E2\u05D1\u05D5\u05E8 [SEARCH_TERM]. \u05DE\u05D5\u05E6\u05D2\u05D5\u05EA \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA \u05E2\u05D1\u05D5\u05E8 [DIFFERENT_TERM]",search_suggestion:"\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA \u05E2\u05D1\u05D5\u05E8 [SEARCH_TERM]. \u05E0\u05E1\u05D5 \u05D0\u05D7\u05D3 \u05DE\u05D4\u05D7\u05D9\u05E4\u05D5\u05E9\u05D9\u05DD \u05D4\u05D1\u05D0\u05D9\u05DD:",searching:"\u05DE\u05D7\u05E4\u05E9 \u05D0\u05EA [SEARCH_TERM]..."},cl={thanks_to:il,comments:al,direction:ol,strings:ul};var Dt={};y(Dt,{comments:()=>fl,default:()=>ml,direction:()=>dl,strings:()=>hl,thanks_to:()=>_l});var _l="Amit Yadav ",fl="",dl="ltr",hl={placeholder:"\u0916\u094B\u091C\u0947\u0902",clear_search:"\u0938\u093E\u092B \u0915\u0930\u0947\u0902",load_more:"\u0914\u0930 \u0905\u0927\u093F\u0915 \u092A\u0930\u093F\u0923\u093E\u092E \u0932\u094B\u0921 \u0915\u0930\u0947\u0902",search_label:"\u0907\u0938 \u0938\u093E\u0907\u091F \u092E\u0947\u0902 \u0916\u094B\u091C\u0947\u0902",filters_label:"\u092B\u093C\u093F\u0932\u094D\u091F\u0930",zero_results:"\u0915\u094B\u0908 \u092A\u0930\u093F\u0923\u093E\u092E [SEARCH_TERM] \u0915\u0947 \u0932\u093F\u090F \u0928\u0939\u0940\u0902 \u092E\u093F\u0932\u093E",many_results:"[COUNT] \u092A\u0930\u093F\u0923\u093E\u092E [SEARCH_TERM] \u0915\u0947 \u0932\u093F\u090F \u092E\u093F\u0932\u0947",one_result:"[COUNT] \u092A\u0930\u093F\u0923\u093E\u092E [SEARCH_TERM] \u0915\u0947 \u0932\u093F\u090F \u092E\u093F\u0932\u093E",alt_search:"[SEARCH_TERM] \u0915\u0947 \u0932\u093F\u090F \u0915\u094B\u0908 \u092A\u0930\u093F\u0923\u093E\u092E \u0928\u0939\u0940\u0902 \u092E\u093F\u0932\u093E\u0964 \u0907\u0938\u0915\u0947 \u092C\u091C\u093E\u092F [DIFFERENT_TERM] \u0915\u0947 \u0932\u093F\u090F \u092A\u0930\u093F\u0923\u093E\u092E \u0926\u093F\u0916\u093E \u0930\u0939\u093E \u0939\u0948",search_suggestion:"[SEARCH_TERM] \u0915\u0947 \u0932\u093F\u090F \u0915\u094B\u0908 \u092A\u0930\u093F\u0923\u093E\u092E \u0928\u0939\u0940\u0902 \u092E\u093F\u0932\u093E\u0964 \u0928\u093F\u092E\u094D\u0928\u0932\u093F\u0916\u093F\u0924 \u0916\u094B\u091C\u094B\u0902 \u092E\u0947\u0902 \u0938\u0947 \u0915\u094B\u0908 \u090F\u0915 \u0906\u091C\u093C\u092E\u093E\u090F\u0902:",searching:"[SEARCH_TERM] \u0915\u0940 \u0916\u094B\u091C \u0915\u0940 \u091C\u093E \u0930\u0939\u0940 \u0939\u0948..."},ml={thanks_to:_l,comments:fl,direction:dl,strings:hl};var It={};y(It,{comments:()=>gl,default:()=>bl,direction:()=>El,strings:()=>Rl,thanks_to:()=>pl});var pl="Diomed ",gl="",El="ltr",Rl={placeholder:"Tra\u017Ei",clear_search:"O\u010Disti",load_more:"U\u010Ditaj vi\u0161e rezultata",search_label:"Pretra\u017Ei ovu stranicu",filters_label:"Filteri",zero_results:"Nema rezultata za [SEARCH_TERM]",many_results:"[COUNT] rezultata za [SEARCH_TERM]",one_result:"[COUNT] rezultat za [SEARCH_TERM]",alt_search:"Nema rezultata za [SEARCH_TERM]. Prikazujem rezultate za [DIFFERENT_TERM]",search_suggestion:"Nema rezultata za [SEARCH_TERM]. Poku\u0161aj s jednom od ovih pretraga:",searching:"Pretra\u017Eujem [SEARCH_TERM]..."},bl={thanks_to:pl,comments:gl,direction:El,strings:Rl};var Pt={};y(Pt,{comments:()=>Cl,default:()=>yl,direction:()=>kl,strings:()=>Sl,thanks_to:()=>Tl});var Tl="Adam Laki ",Cl="",kl="ltr",Sl={placeholder:"Keres\xE9s",clear_search:"T\xF6rl\xE9s",load_more:"Tov\xE1bbi tal\xE1latok bet\xF6lt\xE9se",search_label:"Keres\xE9s az oldalon",filters_label:"Sz\u0171r\xE9s",zero_results:"Nincs tal\xE1lat a(z) [SEARCH_TERM] kifejez\xE9sre",many_results:"[COUNT] db tal\xE1lat a(z) [SEARCH_TERM] kifejez\xE9sre",one_result:"[COUNT] db tal\xE1lat a(z) [SEARCH_TERM] kifejez\xE9sre",alt_search:"Nincs tal\xE1lat a(z) [SEARCH_TERM] kifejez\xE9sre. Tal\xE1latok mutat\xE1sa ink\xE1bb a(z) [DIFFERENT_TERM] kifejez\xE9sre",search_suggestion:"Nincs tal\xE1lat a(z) [SEARCH_TERM] kifejez\xE9sre. Pr\xF3b\xE1ld meg a k\xF6vetkez\u0151 keres\xE9sek egyik\xE9t:",searching:"Keres\xE9s a(z) [SEARCH_TERM] kifejez\xE9sre..."},yl={thanks_to:Tl,comments:Cl,direction:kl,strings:Sl};var Lt={};y(Lt,{comments:()=>Al,default:()=>Hl,direction:()=>vl,strings:()=>wl,thanks_to:()=>Ml});var Ml="Nixentric",Al="",vl="ltr",wl={placeholder:"Cari",clear_search:"Bersihkan",load_more:"Muat lebih banyak hasil",search_label:"Telusuri situs ini",filters_label:"Filter",zero_results:"[SEARCH_TERM] tidak ditemukan",many_results:"Ditemukan [COUNT] hasil untuk [SEARCH_TERM]",one_result:"Ditemukan [COUNT] hasil untuk [SEARCH_TERM]",alt_search:"[SEARCH_TERM] tidak ditemukan. Menampilkan hasil [DIFFERENT_TERM] sebagai gantinya",search_suggestion:"[SEARCH_TERM] tidak ditemukan. Coba salah satu pencarian berikut ini:",searching:"Mencari [SEARCH_TERM]..."},Hl={thanks_to:Ml,comments:Al,direction:vl,strings:wl};var qt={};y(qt,{comments:()=>Nl,default:()=>zl,direction:()=>Ol,strings:()=>jl,thanks_to:()=>Fl});var Fl="Cosette Bruhns Alonso, Andrew Janco ",Nl="",Ol="ltr",jl={placeholder:"Cerca",clear_search:"Cancella la cronologia",load_more:"Mostra pi\xF9 risultati",search_label:"Cerca nel sito",filters_label:"Filtri di ricerca",zero_results:"Nessun risultato per [SEARCH_TERM]",many_results:"[COUNT] risultati per [SEARCH_TERM]",one_result:"[COUNT] risultato per [SEARCH_TERM]",alt_search:"Nessun risultato per [SEARCH_TERM]. Mostrando risultati per [DIFFERENT_TERM] come alternativa.",search_suggestion:"Nessun risultato per [SEARCH_TERM]. Prova una delle seguenti ricerche:",searching:"Cercando [SEARCH_TERM]..."},zl={thanks_to:Fl,comments:Nl,direction:Ol,strings:jl};var Bt={};y(Bt,{comments:()=>Dl,default:()=>Ll,direction:()=>Il,strings:()=>Pl,thanks_to:()=>Ul});var Ul="Tate",Dl="",Il="ltr",Pl={placeholder:"\u691C\u7D22",clear_search:"\u30AF\u30EA\u30A2",load_more:"\u6B21\u3092\u8AAD\u307F\u8FBC\u3080",search_label:"\u3053\u306E\u30B5\u30A4\u30C8\u3092\u691C\u7D22",filters_label:"\u30D5\u30A3\u30EB\u30BF",zero_results:"[SEARCH_TERM]\u306E\u691C\u7D22\u306B\u4E00\u81F4\u3059\u308B\u60C5\u5831\u306F\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F",many_results:"[SEARCH_TERM]\u306E[COUNT]\u4EF6\u306E\u691C\u7D22\u7D50\u679C",one_result:"[SEARCH_TERM]\u306E[COUNT]\u4EF6\u306E\u691C\u7D22\u7D50\u679C",alt_search:"[SEARCH_TERM]\u306E\u691C\u7D22\u306B\u4E00\u81F4\u3059\u308B\u60C5\u5831\u306F\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002[DIFFERENT_TERM]\u306E\u691C\u7D22\u7D50\u679C\u3092\u8868\u793A\u3057\u3066\u3044\u307E\u3059",search_suggestion:"[SEARCH_TERM]\u306E\u691C\u7D22\u306B\u4E00\u81F4\u3059\u308B\u60C5\u5831\u306F\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u6B21\u306E\u3044\u305A\u308C\u304B\u306E\u691C\u7D22\u3092\u8A66\u3057\u3066\u304F\u3060\u3055\u3044",searching:"[SEARCH_TERM]\u3092\u691C\u7D22\u3057\u3066\u3044\u307E\u3059"},Ll={thanks_to:Ul,comments:Dl,direction:Il,strings:Pl};var Vt={};y(Vt,{comments:()=>Bl,default:()=>Gl,direction:()=>Vl,strings:()=>Wl,thanks_to:()=>ql});var ql="Seokho Son ",Bl="",Vl="ltr",Wl={placeholder:"\uAC80\uC0C9\uC5B4",clear_search:"\uBE44\uC6B0\uAE30",load_more:"\uAC80\uC0C9 \uACB0\uACFC \uB354 \uBCF4\uAE30",search_label:"\uC0AC\uC774\uD2B8 \uAC80\uC0C9",filters_label:"\uD544\uD130",zero_results:"[SEARCH_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC \uC5C6\uC74C",many_results:"[SEARCH_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC [COUNT]\uAC74",one_result:"[SEARCH_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC [COUNT]\uAC74",alt_search:"[SEARCH_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC \uC5C6\uC74C. [DIFFERENT_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC",search_suggestion:"[SEARCH_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC \uC5C6\uC74C. \uCD94\uCC9C \uAC80\uC0C9\uC5B4: ",searching:"[SEARCH_TERM] \uAC80\uC0C9 \uC911..."},Gl={thanks_to:ql,comments:Bl,direction:Vl,strings:Wl};var Wt={};y(Wt,{comments:()=>Jl,default:()=>Xl,direction:()=>Yl,strings:()=>Zl,thanks_to:()=>Kl});var Kl="",Jl="",Yl="ltr",Zl={placeholder:"Rapu",clear_search:"Whakakore",load_more:"Whakauta \u0113tahi otinga k\u0113",search_label:"Rapu",filters_label:"T\u0101tari",zero_results:"Otinga kore ki [SEARCH_TERM]",many_results:"[COUNT] otinga ki [SEARCH_TERM]",one_result:"[COUNT] otinga ki [SEARCH_TERM]",alt_search:"Otinga kore ki [SEARCH_TERM]. Otinga k\u0113 ki [DIFFERENT_TERM]",search_suggestion:"Otinga kore ki [SEARCH_TERM]. whakam\u0101tau ki ng\u0101 mea atu:",searching:"Rapu ki [SEARCH_TERM]..."},Xl={thanks_to:Kl,comments:Jl,direction:Yl,strings:Zl};var Gt={};y(Gt,{comments:()=>xl,default:()=>ti,direction:()=>$l,strings:()=>ei,thanks_to:()=>Ql});var Ql="Paul van Brouwershaven",xl="",$l="ltr",ei={placeholder:"Zoeken",clear_search:"Reset",load_more:"Meer resultaten laden",search_label:"Doorzoek deze site",filters_label:"Filters",zero_results:"Geen resultaten voor [SEARCH_TERM]",many_results:"[COUNT] resultaten voor [SEARCH_TERM]",one_result:"[COUNT] resultaat voor [SEARCH_TERM]",alt_search:"Geen resultaten voor [SEARCH_TERM]. In plaats daarvan worden resultaten voor [DIFFERENT_TERM] weergegeven",search_suggestion:"Geen resultaten voor [SEARCH_TERM]. Probeer een van de volgende zoekopdrachten:",searching:"Zoeken naar [SEARCH_TERM]..."},ti={thanks_to:Ql,comments:xl,direction:$l,strings:ei};var Kt={};y(Kt,{comments:()=>si,default:()=>ii,direction:()=>ri,strings:()=>li,thanks_to:()=>ni});var ni="Christopher Wingate",si="",ri="ltr",li={placeholder:"S\xF8k",clear_search:"Fjern",load_more:"Last flere resultater",search_label:"S\xF8k p\xE5 denne siden",filters_label:"Filtre",zero_results:"Ingen resultater for [SEARCH_TERM]",many_results:"[COUNT] resultater for [SEARCH_TERM]",one_result:"[COUNT] resultat for [SEARCH_TERM]",alt_search:"Ingen resultater for [SEARCH_TERM]. Viser resultater for [DIFFERENT_TERM] i stedet",search_suggestion:"Ingen resultater for [SEARCH_TERM]. Pr\xF8v en av disse s\xF8keordene i stedet:",searching:"S\xF8ker etter [SEARCH_TERM]"},ii={thanks_to:ni,comments:si,direction:ri,strings:li};var Jt={};y(Jt,{comments:()=>oi,default:()=>_i,direction:()=>ui,strings:()=>ci,thanks_to:()=>ai});var ai="",oi="",ui="ltr",ci={placeholder:"Szukaj",clear_search:"Wyczy\u015B\u0107",load_more:"Za\u0142aduj wi\u0119cej",search_label:"Przeszukaj t\u0119 stron\u0119",filters_label:"Filtry",zero_results:"Brak wynik\xF3w dla [SEARCH_TERM]",many_results:"[COUNT] wynik\xF3w dla [SEARCH_TERM]",one_result:"[COUNT] wynik dla [SEARCH_TERM]",alt_search:"Brak wynik\xF3w dla [SEARCH_TERM]. Wy\u015Bwietlam wyniki dla [DIFFERENT_TERM]",search_suggestion:"Brak wynik\xF3w dla [SEARCH_TERM]. Pokrewne wyniki wyszukiwania:",searching:"Szukam [SEARCH_TERM]..."},_i={thanks_to:ai,comments:oi,direction:ui,strings:ci};var Yt={};y(Yt,{comments:()=>di,default:()=>pi,direction:()=>hi,strings:()=>mi,thanks_to:()=>fi});var fi="Jonatah",di="",hi="ltr",mi={placeholder:"Pesquisar",clear_search:"Limpar",load_more:"Ver mais resultados",search_label:"Pesquisar",filters_label:"Filtros",zero_results:"Nenhum resultado encontrado para [SEARCH_TERM]",many_results:"[COUNT] resultados encontrados para [SEARCH_TERM]",one_result:"[COUNT] resultado encontrado para [SEARCH_TERM]",alt_search:"Nenhum resultado encontrado para [SEARCH_TERM]. Exibindo resultados para [DIFFERENT_TERM]",search_suggestion:"Nenhum resultado encontrado para [SEARCH_TERM]. Tente uma das seguintes pesquisas:",searching:"Pesquisando por [SEARCH_TERM]..."},pi={thanks_to:fi,comments:di,direction:hi,strings:mi};var Zt={};y(Zt,{comments:()=>Ei,default:()=>Ti,direction:()=>Ri,strings:()=>bi,thanks_to:()=>gi});var gi="Bogdan Mateescu ",Ei="",Ri="ltr",bi={placeholder:"C\u0103utare",clear_search:"\u015Eterge\u0163i",load_more:"\xCEnc\u0103rca\u021Bi mai multe rezultate",search_label:"C\u0103uta\u021Bi \xEEn acest site",filters_label:"Filtre",zero_results:"Niciun rezultat pentru [SEARCH_TERM]",many_results:"[COUNT] rezultate pentru [SEARCH_TERM]",one_result:"[COUNT] rezultat pentru [SEARCH_TERM]",alt_search:"Niciun rezultat pentru [SEARCH_TERM]. Se afi\u0219eaz\u0103 \xEEn schimb rezultatele pentru [DIFFERENT_TERM]",search_suggestion:"Niciun rezultat pentru [SEARCH_TERM]. \xCEncerca\u021Bi una dintre urm\u0103toarele c\u0103ut\u0103ri:",searching:"Se caut\u0103 dup\u0103: [SEARCH_TERM]..."},Ti={thanks_to:gi,comments:Ei,direction:Ri,strings:bi};var Xt={};y(Xt,{comments:()=>ki,default:()=>Mi,direction:()=>Si,strings:()=>yi,thanks_to:()=>Ci});var Ci="Aleksandr Gordeev",ki="",Si="ltr",yi={placeholder:"\u041F\u043E\u0438\u0441\u043A",clear_search:"\u041E\u0447\u0438\u0441\u0442\u0438\u0442\u044C \u043F\u043E\u043B\u0435",load_more:"\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0435\u0449\u0435",search_label:"\u041F\u043E\u0438\u0441\u043A \u043F\u043E \u0441\u0430\u0439\u0442\u0443",filters_label:"\u0424\u0438\u043B\u044C\u0442\u0440\u044B",zero_results:"\u041D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]",many_results:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u043E\u0432 \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]",one_result:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]",alt_search:"\u041D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]. \u041F\u043E\u043A\u0430\u0437\u0430\u043D\u044B \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [DIFFERENT_TERM]",search_suggestion:"\u041D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]. \u041F\u043E\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u043E\u0434\u0438\u043D \u0438\u0437 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0445 \u0432\u0430\u0440\u0438\u0430\u043D\u0442\u043E\u0432",searching:"\u041F\u043E\u0438\u0441\u043A \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]"},Mi={thanks_to:Ci,comments:ki,direction:Si,strings:yi};var Qt={};y(Qt,{comments:()=>vi,default:()=>Fi,direction:()=>wi,strings:()=>Hi,thanks_to:()=>Ai});var Ai="Andrija Sagicc",vi="",wi="ltr",Hi={placeholder:"\u041F\u0440\u0435\u0442\u0440\u0430\u0433\u0430",clear_search:"\u0411\u0440\u0438\u0441\u0430\u045A\u0435",load_more:"\u041F\u0440\u0438\u043A\u0430\u0437 \u0432\u0438\u0448\u0435 \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430",search_label:"\u041F\u0440\u0435\u0442\u0440\u0430\u0433\u0430 \u0441\u0430\u0458\u0442\u0430",filters_label:"\u0424\u0438\u043B\u0442\u0435\u0440\u0438",zero_results:"\u041D\u0435\u043C\u0430 \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [SEARCH_TERM]",many_results:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [SEARCH_TERM]",one_result:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [SEARCH_TERM]",alt_search:"\u041D\u0435\u043C\u0430 \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [SEARCH_TERM]. \u041F\u0440\u0438\u043A\u0430\u0437 \u0434\u043E\u0434\u0430\u0442\u043D\u0438\u043A \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [DIFFERENT_TERM]",search_suggestion:"\u041D\u0435\u043C\u0430 \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [SEARCH_TERM]. \u041F\u043E\u043A\u0443\u0448\u0430\u0458\u0442\u0435 \u0441\u0430 \u043D\u0435\u043A\u043E\u043C \u043E\u0434 \u0441\u043B\u0435\u0434\u0435\u045B\u0438\u0445 \u043F\u0440\u0435\u0442\u0440\u0430\u0433\u0430:",searching:"\u041F\u0440\u0435\u0442\u0440\u0430\u0433\u0430 \u0442\u0435\u0440\u043C\u0438\u043D\u0430 [SEARCH_TERM]..."},Fi={thanks_to:Ai,comments:vi,direction:wi,strings:Hi};var xt={};y(xt,{comments:()=>Oi,default:()=>Ui,direction:()=>ji,strings:()=>zi,thanks_to:()=>Ni});var Ni="Montazar Al-Jaber ",Oi="",ji="ltr",zi={placeholder:"S\xF6k",clear_search:"Rensa",load_more:"Visa fler tr\xE4ffar",search_label:"S\xF6k p\xE5 denna sida",filters_label:"Filter",zero_results:"[SEARCH_TERM] gav inga tr\xE4ffar",many_results:"[SEARCH_TERM] gav [COUNT] tr\xE4ffar",one_result:"[SEARCH_TERM] gav [COUNT] tr\xE4ff",alt_search:"[SEARCH_TERM] gav inga tr\xE4ffar. Visar resultat f\xF6r [DIFFERENT_TERM] ist\xE4llet",search_suggestion:"[SEARCH_TERM] gav inga tr\xE4ffar. F\xF6rs\xF6k igen med en av f\xF6ljande s\xF6kord:",searching:"S\xF6ker efter [SEARCH_TERM]..."},Ui={thanks_to:Ni,comments:Oi,direction:ji,strings:zi};var $t={};y($t,{comments:()=>Ii,default:()=>qi,direction:()=>Pi,strings:()=>Li,thanks_to:()=>Di});var Di="Anonymous",Ii="",Pi="ltr",Li={placeholder:"Tafuta",clear_search:"Futa",load_more:"Pakia matokeo zaidi",search_label:"Tafuta tovuti hii",filters_label:"Vichujio",zero_results:"Hakuna matokeo ya [SEARCH_TERM]",many_results:"Matokeo [COUNT] ya [SEARCH_TERM]",one_result:"Tokeo [COUNT] la [SEARCH_TERM]",alt_search:"Hakuna mayokeo ya [SEARCH_TERM]. Badala yake, inaonyesha matokeo ya [DIFFERENT_TERM]",search_suggestion:"Hakuna matokeo ya [SEARCH_TERM]. Jaribu mojawapo ya utafutaji ufuatao:",searching:"Kutafuta [SEARCH_TERM]..."},qi={thanks_to:Di,comments:Ii,direction:Pi,strings:Li};var en={};y(en,{comments:()=>Vi,default:()=>Ki,direction:()=>Wi,strings:()=>Gi,thanks_to:()=>Bi});var Bi="",Vi="",Wi="ltr",Gi={placeholder:"\u0BA4\u0BC7\u0B9F\u0BC1\u0B95",clear_search:"\u0B85\u0BB4\u0BBF\u0B95\u0BCD\u0B95\u0BC1\u0B95",load_more:"\u0BAE\u0BC7\u0BB2\u0BC1\u0BAE\u0BCD \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BC8\u0B95\u0BCD \u0B95\u0BBE\u0B9F\u0BCD\u0B9F\u0BC1\u0B95",search_label:"\u0B87\u0BA8\u0BCD\u0BA4 \u0BA4\u0BB3\u0BA4\u0BCD\u0BA4\u0BBF\u0BB2\u0BCD \u0BA4\u0BC7\u0B9F\u0BC1\u0B95",filters_label:"\u0BB5\u0B9F\u0BBF\u0B95\u0B9F\u0BCD\u0B9F\u0BB2\u0BCD\u0B95\u0BB3\u0BCD",zero_results:"[SEARCH_TERM] \u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BCD \u0B87\u0BB2\u0BCD\u0BB2\u0BC8",many_results:"[SEARCH_TERM] \u0B95\u0BCD\u0B95\u0BBE\u0BA9 [COUNT] \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BCD",one_result:"[SEARCH_TERM] \u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1",alt_search:"[SEARCH_TERM] \u0B87\u0BA4\u0BCD\u0BA4\u0BC7\u0B9F\u0BB2\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BCD \u0B87\u0BB2\u0BCD\u0BB2\u0BC8, \u0B87\u0BA8\u0BCD\u0BA4 \u0BA4\u0BC7\u0B9F\u0BB2\u0BCD\u0B95\u0BB3\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0B92\u0BA4\u0BCD\u0BA4 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BCD [DIFFERENT_TERM]",search_suggestion:"[SEARCH_TERM] \u0B87\u0BA4\u0BCD \u0BA4\u0BC7\u0B9F\u0BB2\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BCD \u0B87\u0BB2\u0BCD\u0BB2\u0BC8.\u0B87\u0BA4\u0BB1\u0BCD\u0B95\u0BC1 \u0BAA\u0BA4\u0BBF\u0BB2\u0BC0\u0B9F\u0BBE\u0BA9 \u0BA4\u0BC7\u0B9F\u0BB2\u0BCD\u0B95\u0BB3\u0BC8 \u0BA4\u0BC7\u0B9F\u0BC1\u0B95:",searching:"[SEARCH_TERM] \u0BA4\u0BC7\u0B9F\u0BAA\u0BCD\u0BAA\u0B9F\u0BC1\u0B95\u0BBF\u0BA9\u0BCD\u0BB1\u0BA4\u0BC1"},Ki={thanks_to:Bi,comments:Vi,direction:Wi,strings:Gi};var tn={};y(tn,{comments:()=>Yi,default:()=>Qi,direction:()=>Zi,strings:()=>Xi,thanks_to:()=>Ji});var Ji="Taylan \xD6zg\xFCr Bildik",Yi="",Zi="ltr",Xi={placeholder:"Ara\u015Ft\u0131r",clear_search:"Temizle",load_more:"Daha fazla sonu\xE7",search_label:"Site genelinde arama",filters_label:"Filtreler",zero_results:"[SEARCH_TERM] i\xE7in sonu\xE7 yok",many_results:"[SEARCH_TERM] i\xE7in [COUNT] sonu\xE7 bulundu",one_result:"[SEARCH_TERM] i\xE7in [COUNT] sonu\xE7 bulundu",alt_search:"[SEARCH_TERM] i\xE7in sonu\xE7 yok. Bunun yerine [DIFFERENT_TERM] i\xE7in sonu\xE7lar g\xF6steriliyor",search_suggestion:"[SEARCH_TERM] i\xE7in sonu\xE7 yok. Alternatif olarak a\u015Fa\u011F\u0131daki kelimelerden birini deneyebilirsiniz:",searching:"[SEARCH_TERM] ara\u015Ft\u0131r\u0131l\u0131yor..."},Qi={thanks_to:Ji,comments:Yi,direction:Zi,strings:Xi};var nn={};y(nn,{comments:()=>$i,default:()=>na,direction:()=>ea,strings:()=>ta,thanks_to:()=>xi});var xi="Vladyslav Lyshenko ",$i="",ea="ltr",ta={placeholder:"\u041F\u043E\u0448\u0443\u043A",clear_search:"\u041E\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u043F\u043E\u043B\u0435",load_more:"\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0449\u0435",search_label:"\u041F\u043E\u0448\u0443\u043A \u043F\u043E \u0441\u0430\u0439\u0442\u0443",filters_label:"\u0424\u0456\u043B\u044C\u0442\u0440\u0438",zero_results:"\u041D\u0456\u0447\u043E\u0433\u043E \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E \u0437\u0430 \u0437\u0430\u043F\u0438\u0442\u043E\u043C: [SEARCH_TERM]",many_results:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u0456\u0432 \u043D\u0430 \u0437\u0430\u043F\u0438\u0442: [SEARCH_TERM]",one_result:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 \u0437\u0430 \u0437\u0430\u043F\u0438\u0442\u043E\u043C: [SEARCH_TERM]",alt_search:"\u041D\u0456\u0447\u043E\u0433\u043E \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043D\u0430 \u0437\u0430\u043F\u0438\u0442: [SEARCH_TERM]. \u041F\u043E\u043A\u0430\u0437\u0430\u043D\u043E \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u0438 \u043D\u0430 \u0437\u0430\u043F\u0438\u0442: [DIFFERENT_TERM]",search_suggestion:"\u041D\u0456\u0447\u043E\u0433\u043E \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043D\u0430 \u0437\u0430\u043F\u0438\u0442: [SEARCH_TERM]. \u0421\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u043E\u0434\u0438\u043D \u0456\u0437 \u0442\u0430\u043A\u0438\u0445 \u0432\u0430\u0440\u0456\u0430\u043D\u0442\u0456\u0432",searching:"\u041F\u043E\u0448\u0443\u043A \u0437\u0430 \u0437\u0430\u043F\u0438\u0442\u043E\u043C: [SEARCH_TERM]"},na={thanks_to:xi,comments:$i,direction:ea,strings:ta};var sn={};y(sn,{comments:()=>ra,default:()=>aa,direction:()=>la,strings:()=>ia,thanks_to:()=>sa});var sa="Long Nhat Nguyen",ra="",la="ltr",ia={placeholder:"T\xECm ki\u1EBFm",clear_search:"X\xF3a",load_more:"Nhi\u1EC1u k\u1EBFt qu\u1EA3 h\u01A1n",search_label:"T\xECm ki\u1EBFm trong trang n\xE0y",filters_label:"B\u1ED9 l\u1ECDc",zero_results:"Kh\xF4ng t\xECm th\u1EA5y k\u1EBFt qu\u1EA3 cho [SEARCH_TERM]",many_results:"[COUNT] k\u1EBFt qu\u1EA3 cho [SEARCH_TERM]",one_result:"[COUNT] k\u1EBFt qu\u1EA3 cho [SEARCH_TERM]",alt_search:"Kh\xF4ng t\xECm th\u1EA5y k\u1EBFt qu\u1EA3 cho [SEARCH_TERM]. Ki\u1EC3m th\u1ECB k\u1EBFt qu\u1EA3 thay th\u1EBF v\u1EDBi [DIFFERENT_TERM]",search_suggestion:"Kh\xF4ng t\xECm th\u1EA5y k\u1EBFt qu\u1EA3 cho [SEARCH_TERM]. Th\u1EED m\u1ED9t trong c\xE1c t\xECm ki\u1EBFm:",searching:"\u0110ang t\xECm ki\u1EBFm cho [SEARCH_TERM]..."},aa={thanks_to:sa,comments:ra,direction:la,strings:ia};var rn={};y(rn,{comments:()=>ua,default:()=>fa,direction:()=>ca,strings:()=>_a,thanks_to:()=>oa});var oa="Amber Song",ua="",ca="ltr",_a={placeholder:"\u641C\u7D22",clear_search:"\u6E05\u9664",load_more:"\u52A0\u8F7D\u66F4\u591A\u7ED3\u679C",search_label:"\u7AD9\u5185\u641C\u7D22",filters_label:"\u7B5B\u9009",zero_results:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",many_results:"\u627E\u5230 [COUNT] \u4E2A [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",one_result:"\u627E\u5230 [COUNT] \u4E2A [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",alt_search:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C\u3002\u6539\u4E3A\u663E\u793A [DIFFERENT_TERM] \u7684\u76F8\u5173\u7ED3\u679C",search_suggestion:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C\u3002\u8BF7\u5C1D\u8BD5\u4EE5\u4E0B\u641C\u7D22\u3002",searching:"\u6B63\u5728\u641C\u7D22 [SEARCH_TERM]..."},fa={thanks_to:oa,comments:ua,direction:ca,strings:_a};var ln={};y(ln,{comments:()=>ha,default:()=>ga,direction:()=>ma,strings:()=>pa,thanks_to:()=>da});var da="Amber Song",ha="",ma="ltr",pa={placeholder:"\u641C\u7D22",clear_search:"\u6E05\u9664",load_more:"\u52A0\u8F09\u66F4\u591A\u7D50\u679C",search_label:"\u7AD9\u5167\u641C\u7D22",filters_label:"\u7BE9\u9078",zero_results:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u95DC\u7D50\u679C",many_results:"\u627E\u5230 [COUNT] \u500B [SEARCH_TERM] \u7684\u76F8\u95DC\u7D50\u679C",one_result:"\u627E\u5230 [COUNT] \u500B [SEARCH_TERM] \u7684\u76F8\u95DC\u7D50\u679C",alt_search:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u95DC\u7D50\u679C\u3002\u6539\u70BA\u986F\u793A [DIFFERENT_TERM] \u7684\u76F8\u95DC\u7D50\u679C",search_suggestion:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u95DC\u7D50\u679C\u3002\u8ACB\u5617\u8A66\u4EE5\u4E0B\u641C\u7D22\u3002",searching:"\u6B63\u5728\u641C\u7D22 [SEARCH_TERM]..."},ga={thanks_to:da,comments:ha,direction:ma,strings:pa};var an={};y(an,{comments:()=>Ra,default:()=>Ca,direction:()=>ba,strings:()=>Ta,thanks_to:()=>Ea});var Ea="Amber Song",Ra="",ba="ltr",Ta={placeholder:"\u641C\u7D22",clear_search:"\u6E05\u9664",load_more:"\u52A0\u8F7D\u66F4\u591A\u7ED3\u679C",search_label:"\u7AD9\u5185\u641C\u7D22",filters_label:"\u7B5B\u9009",zero_results:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",many_results:"\u627E\u5230 [COUNT] \u4E2A [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",one_result:"\u627E\u5230 [COUNT] \u4E2A [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",alt_search:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C\u3002\u6539\u4E3A\u663E\u793A [DIFFERENT_TERM] \u7684\u76F8\u5173\u7ED3\u679C",search_suggestion:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C\u3002\u8BF7\u5C1D\u8BD5\u4EE5\u4E0B\u641C\u7D22\u3002",searching:"\u6B63\u5728\u641C\u7D22 [SEARCH_TERM]..."},Ca={thanks_to:Ea,comments:Ra,direction:ba,strings:Ta};var ka=[kt,St,yt,Mt,At,vt,wt,Ht,Ft,Nt,Ot,jt,zt,Ut,Dt,It,Pt,Lt,qt,Bt,Vt,Wt,Gt,Kt,Jt,Yt,Zt,Xt,Qt,xt,$t,en,tn,nn,sn,rn,ln,an],ss=ka,rs=["../../translations/af.json","../../translations/ar.json","../../translations/bn.json","../../translations/ca.json","../../translations/cs.json","../../translations/da.json","../../translations/de.json","../../translations/en.json","../../translations/es.json","../../translations/fa.json","../../translations/fi.json","../../translations/fr.json","../../translations/gl.json","../../translations/he.json","../../translations/hi.json","../../translations/hr.json","../../translations/hu.json","../../translations/id.json","../../translations/it.json","../../translations/ja.json","../../translations/ko.json","../../translations/mi.json","../../translations/nl.json","../../translations/no.json","../../translations/pl.json","../../translations/pt.json","../../translations/ro.json","../../translations/ru.json","../../translations/sr.json","../../translations/sv.json","../../translations/sw.json","../../translations/ta.json","../../translations/tr.json","../../translations/uk.json","../../translations/vi.json","../../translations/zh-cn.json","../../translations/zh-tw.json","../../translations/zh.json"];function ls(n,e,t){let s=n.slice();return s[51]=e[t],s}function is(n){let e,t,s;function r(i){n[37](i)}let l={show_empty_filters:n[5],open_filters:n[6],available_filters:n[18],translate:n[20],automatic_translations:n[19],translations:n[7]};return n[0]!==void 0&&(l.selected_filters=n[0]),e=new ns({props:l}),le.push(()=>Mn(e,"selected_filters",r)),{c(){rt(e.$$.fragment)},m(i,a){me(e,i,a),s=!0},p(i,a){let o={};a[0]&32&&(o.show_empty_filters=i[5]),a[0]&64&&(o.open_filters=i[6]),a[0]&262144&&(o.available_filters=i[18]),a[0]&524288&&(o.automatic_translations=i[19]),a[0]&128&&(o.translations=i[7]),!t&&a[0]&1&&(t=!0,o.selected_filters=i[0],Cn(()=>t=!1)),e.$set(o)},i(i){s||(U(e.$$.fragment,i),s=!0)},o(i){P(e.$$.fragment,i),s=!1},d(i){ue(e,i)}}}function as(n){let e,t,s,r,l=[Ma,ya],i=[];function a(o,f){return o[14]?0:1}return t=a(n,[-1,-1]),s=i[t]=l[t](n),{c(){e=C("div"),s.c(),g(e,"class","pagefind-ui__results-area svelte-e9gkc3")},m(o,f){S(o,e,f),i[t].m(e,null),r=!0},p(o,f){let u=t;t=a(o,f),t===u?i[t].p(o,f):(ae(),P(i[u],1,1,()=>{i[u]=null}),oe(),s=i[t],s?s.p(o,f):(s=i[t]=l[t](o),s.c()),U(s,1),s.m(e,null))},i(o){r||(U(s),r=!0)},o(o){P(s),r=!1},d(o){o&&k(e),i[t].d()}}}function ya(n){let e,t,s,r=[],l=new Map,i,a,o;function f(c,d){return c[13].results.length===0?wa:c[13].results.length===1?va:Aa}let u=f(n,[-1,-1]),m=u(n),p=n[13].results.slice(0,n[17]),h=c=>c[51].id;for(let c=0;cn[17]&&us(n);return{c(){e=C("p"),m.c(),t=A(),s=C("ol");for(let c=0;cc[17]?_?_.p(c,d):(_=us(c),_.c(),_.m(a.parentNode,a)):_&&(_.d(1),_=null)},i(c){if(!o){for(let d=0;d{o[p]=null}),oe(),r=o[s],r?r.p(e,m):(r=o[s]=a[s](e),r.c()),U(r,1),r.m(l.parentNode,l))},i(u){i||(U(r),i=!0)},o(u){P(r),i=!1},d(u){u&&k(t),o[s].d(u),u&&k(l)}}}function us(n){let e,t=n[20]("load_more",n[19],n[7])+"",s,r,l;return{c(){e=C("button"),s=w(t),g(e,"type","button"),g(e,"class","pagefind-ui__button svelte-e9gkc3")},m(i,a){S(i,e,a),b(e,s),r||(l=J(e,"click",n[22]),r=!0)},p(i,a){a[0]&524416&&t!==(t=i[20]("load_more",i[19],i[7])+"")&&N(s,t)},d(i){i&&k(e),r=!1,l()}}}function cs(n){let e,t=n[20]("searching",n[19],n[7]).replace(/\[SEARCH_TERM\]/,n[16])+"",s;return{c(){e=C("p"),s=w(t),g(e,"class","pagefind-ui__message svelte-e9gkc3")},m(r,l){S(r,e,l),b(e,s)},p(r,l){l[0]&589952&&t!==(t=r[20]("searching",r[19],r[7]).replace(/\[SEARCH_TERM\]/,r[16])+"")&&N(s,t)},d(r){r&&k(e)}}}function Na(n){let e,t,s,r,l,i,a=n[20]("clear_search",n[19],n[7])+"",o,f,u,m,p,h,_,c,d=n[12]&&is(n),T=n[15]&&as(n);return{c(){e=C("div"),t=C("form"),s=C("input"),l=A(),i=C("button"),o=w(a),f=A(),u=C("div"),d&&d.c(),m=A(),T&&T.c(),g(s,"class","pagefind-ui__search-input svelte-e9gkc3"),g(s,"type","text"),g(s,"placeholder",r=n[20]("placeholder",n[19],n[7])),g(s,"autocapitalize","none"),g(s,"enterkeyhint","search"),s.autofocus=n[8],g(i,"class","pagefind-ui__search-clear svelte-e9gkc3"),B(i,"pagefind-ui__suppressed",!n[9]),g(u,"class","pagefind-ui__drawer svelte-e9gkc3"),B(u,"pagefind-ui__hidden",!n[15]),g(t,"class","pagefind-ui__form svelte-e9gkc3"),g(t,"role","search"),g(t,"aria-label",p=n[20]("search_label",n[19],n[7])),g(t,"action","javascript:void(0);"),g(e,"class","pagefind-ui svelte-e9gkc3"),B(e,"pagefind-ui--reset",n[1])},m(R,M){S(R,e,M),b(e,t),b(t,s),pt(s,n[9]),n[34](s),b(t,l),b(t,i),b(i,o),n[35](i),b(t,f),b(t,u),d&&d.m(u,null),b(u,m),T&&T.m(u,null),h=!0,n[8]&&s.focus(),_||(c=[J(s,"focus",n[21]),J(s,"keydown",n[32]),J(s,"input",n[33]),J(i,"click",n[36]),J(t,"submit",Oa)],_=!0)},p(R,M){(!h||M[0]&524416&&r!==(r=R[20]("placeholder",R[19],R[7])))&&g(s,"placeholder",r),(!h||M[0]&256)&&(s.autofocus=R[8]),M[0]&512&&s.value!==R[9]&&pt(s,R[9]),(!h||M[0]&524416)&&a!==(a=R[20]("clear_search",R[19],R[7])+"")&&N(o,a),(!h||M[0]&512)&&B(i,"pagefind-ui__suppressed",!R[9]),R[12]?d?(d.p(R,M),M[0]&4096&&U(d,1)):(d=is(R),d.c(),U(d,1),d.m(u,m)):d&&(ae(),P(d,1,1,()=>{d=null}),oe()),R[15]?T?(T.p(R,M),M[0]&32768&&U(T,1)):(T=as(R),T.c(),U(T,1),T.m(u,null)):T&&(ae(),P(T,1,1,()=>{T=null}),oe()),(!h||M[0]&32768)&&B(u,"pagefind-ui__hidden",!R[15]),(!h||M[0]&524416&&p!==(p=R[20]("search_label",R[19],R[7])))&&g(t,"aria-label",p),(!h||M[0]&2)&&B(e,"pagefind-ui--reset",R[1])},i(R){h||(U(d),U(T),h=!0)},o(R){P(d),P(T),h=!1},d(R){R&&k(e),n[34](null),n[35](null),d&&d.d(),T&&T.d(),_=!1,G(c)}}}var Oa=n=>n.preventDefault();function ja(n,e,t){let s={},r=rs.map(E=>E.match(/([^\/]+)\.json$/)[1]);for(let E=0;Ej[E]??F[E]??"";gt(()=>{let E=document?.querySelector?.("html")?.getAttribute?.("lang")||"en",F=lt(E.toLocaleLowerCase());t(19,hn=s[`${F.language}-${F.script}-${F.region}`]||s[`${F.language}-${F.region}`]||s[`${F.language}`]||s.en)}),Et(()=>{H?.destroy?.(),H=null});let mn=async()=>{if(!at&&(t(12,at=!0),!H)){let E;try{E=await import(`${l}pagefind.js`)}catch(j){console.error(j),console.error([`Pagefind couldn't be loaded from ${this.options.bundlePath}pagefind.js`,"You can configure this by passing a bundlePath option to PagefindUI"].join(` +`)),document?.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?console.error(`[DEBUG: Loaded from ${document.currentScript.src??"bad script location"}]`):console.error("no known script location")}u||t(24,u=f?12:30);let F={...d||{},excerptLength:u};await E.options(F);for(let j of T){if(!j.bundlePath)throw new Error("mergeIndex requires a bundlePath parameter");let L=j.bundlePath;delete j.bundlePath,await E.mergeIndex(L,j)}H=E,hs()}},hs=async()=>{H&&(dn=await H.filters(),(!ce||!Object.keys(ce).length)&&t(18,ce=dn))},ms=E=>{let F={};return Object.entries(E).filter(([,j])=>j).forEach(([j])=>{let[L,te]=j.split(/:(.*)$/);F[L]=F[L]||[],F[L].push(te)}),F},_e,ps=async(E,F)=>{if(!E){t(15,ut=!1),_e&&clearTimeout(_e);return}let j=ms(F),L=()=>gs(E,j);c>0&&E?(_e&&clearTimeout(_e),_e=setTimeout(L,c),await pn(),H.preload(E,{filters:j})):L(),Es()},pn=async()=>{for(;!H;)mn(),await new Promise(E=>setTimeout(E,50))},gs=async(E,F)=>{t(16,fn=E||""),typeof p=="function"&&(E=p(E)),t(14,ot=!0),t(15,ut=!0),await pn();let j=++_n,L={filters:F};X&&typeof X=="object"&&(L.sort=X);let te=await H.search(E,L);_n===j&&(te.filters&&Object.keys(te.filters)?.length&&t(18,ce=te.filters),t(13,cn=te),t(14,ot=!1),t(17,ct=i))},Es=()=>{let E=W.offsetWidth;E!=fs&&t(10,O.style.paddingRight=`${E+2}px`,O)},Rs=E=>{E?.preventDefault(),t(17,ct+=i)},bs=E=>{E.key==="Escape"&&(t(9,v=""),O.blur()),E.key==="Enter"&&E.preventDefault()};function Ts(){v=this.value,t(9,v),t(23,R)}function Cs(E){le[E?"unshift":"push"](()=>{O=E,t(10,O)})}function ks(E){le[E?"unshift":"push"](()=>{W=E,t(11,W)})}let Ss=()=>{t(9,v=""),O.blur()};function ys(E){V=E,t(0,V)}return n.$$set=E=>{"base_path"in E&&t(25,l=E.base_path),"page_size"in E&&t(26,i=E.page_size),"reset_styles"in E&&t(1,a=E.reset_styles),"show_images"in E&&t(2,o=E.show_images),"show_sub_results"in E&&t(3,f=E.show_sub_results),"excerpt_length"in E&&t(24,u=E.excerpt_length),"process_result"in E&&t(4,m=E.process_result),"process_term"in E&&t(27,p=E.process_term),"show_empty_filters"in E&&t(5,h=E.show_empty_filters),"open_filters"in E&&t(6,_=E.open_filters),"debounce_timeout_ms"in E&&t(28,c=E.debounce_timeout_ms),"pagefind_options"in E&&t(29,d=E.pagefind_options),"merge_index"in E&&t(30,T=E.merge_index),"trigger_search_term"in E&&t(23,R=E.trigger_search_term),"translations"in E&&t(7,M=E.translations),"autofocus"in E&&t(8,D=E.autofocus),"sort"in E&&t(31,X=E.sort),"selected_filters"in E&&t(0,V=E.selected_filters)},n.$$.update=()=>{if(n.$$.dirty[0]&8388608)e:R&&(t(9,v=R),t(23,R=""));if(n.$$.dirty[0]&513)e:ps(v,V)},[V,a,o,f,m,h,_,M,D,v,O,W,at,cn,ot,ut,fn,ct,ce,hn,ds,mn,Rs,R,u,l,i,p,c,d,T,X,bs,Ts,Cs,ks,Ss,ys]}var on=class extends q{constructor(e){super(),Y(this,e,ja,Na,K,{base_path:25,page_size:26,reset_styles:1,show_images:2,show_sub_results:3,excerpt_length:24,process_result:4,process_term:27,show_empty_filters:5,open_filters:6,debounce_timeout_ms:28,pagefind_options:29,merge_index:30,trigger_search_term:23,translations:7,autofocus:8,sort:31,selected_filters:0},null,[-1,-1])}},_s=on;var un;try{document?.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"&&(un=new URL(document.currentScript.src).pathname.match(/^(.*\/)(?:pagefind-)?ui.js.*$/)[1])}catch{un="/pagefind/"}var it=class{constructor(e){this._pfs=null;let t=e.element??"[data-pagefind-ui]",s=e.bundlePath??un,r=e.pageSize??5,l=e.resetStyles??!0,i=e.showImages??!0,a=e.showSubResults??!1,o=e.excerptLength??0,f=e.processResult??null,u=e.processTerm??null,m=e.showEmptyFilters??!0,p=e.openFilters??[],h=e.debounceTimeoutMs??300,_=e.mergeIndex??[],c=e.translations??[],d=e.autofocus??!1,T=e.sort??null;delete e.element,delete e.bundlePath,delete e.pageSize,delete e.resetStyles,delete e.showImages,delete e.showSubResults,delete e.excerptLength,delete e.processResult,delete e.processTerm,delete e.showEmptyFilters,delete e.openFilters,delete e.debounceTimeoutMs,delete e.mergeIndex,delete e.translations,delete e.autofocus,delete e.sort;let R=t instanceof HTMLElement?t:document.querySelector(t);R?this._pfs=new _s({target:R,props:{base_path:s,page_size:r,reset_styles:l,show_images:i,show_sub_results:a,excerpt_length:o,process_result:f,process_term:u,show_empty_filters:m,open_filters:p,debounce_timeout_ms:h,merge_index:_,translations:c,autofocus:d,sort:T,pagefind_options:e}}):console.error(`Pagefind UI couldn't find the selector ${t}`)}triggerSearch(e){this._pfs.$$set({trigger_search_term:e})}triggerFilters(e){let t={};for(let[s,r]of Object.entries(e))if(Array.isArray(r))for(let l of r)t[`${s}:${l}`]=!0;else t[`${s}:${r}`]=!0;this._pfs.$$set({selected_filters:t})}destroy(){this._pfs.$destroy()}};window.PagefindUI=it;})(); diff --git a/public/pagefind/pagefind.en_757c45eb84.pf_meta b/public/pagefind/pagefind.en_757c45eb84.pf_meta new file mode 100644 index 0000000..cd139fc Binary files /dev/null and b/public/pagefind/pagefind.en_757c45eb84.pf_meta differ diff --git a/public/pagefind/pagefind.js b/public/pagefind/pagefind.js new file mode 100644 index 0000000..035a438 --- /dev/null +++ b/public/pagefind/pagefind.js @@ -0,0 +1,9 @@ +const pagefind_version="1.3.0";let wasm_bindgen;(function(){const __exports={};let script_src;if(typeof document!=='undefined'&&document.currentScript!==null){script_src=new URL("UNHANDLED",location.href).toString()}let wasm=undefined;let cachedUint8Memory0=null;function getUint8Memory0(){if(cachedUint8Memory0===null||cachedUint8Memory0.byteLength===0){cachedUint8Memory0=new Uint8Array(wasm.memory.buffer)}return cachedUint8Memory0}let WASM_VECTOR_LEN=0;function passArray8ToWasm0(arg,malloc){const ptr=malloc(arg.length*1,1)>>>0;getUint8Memory0().set(arg,ptr/1);WASM_VECTOR_LEN=arg.length;return ptr}__exports.init_pagefind=function(metadata_bytes){const ptr0=passArray8ToWasm0(metadata_bytes,wasm.__wbindgen_malloc);const len0=WASM_VECTOR_LEN;const ret=wasm.init_pagefind(ptr0,len0);return ret>>>0};const cachedTextEncoder=(typeof TextEncoder!=='undefined'?new TextEncoder('utf-8'):{encode:()=>{throw Error('TextEncoder not available')}});const encodeString=(typeof cachedTextEncoder.encodeInto==='function'?function(arg,view){return cachedTextEncoder.encodeInto(arg,view)}:function(arg,view){const buf=cachedTextEncoder.encode(arg);view.set(buf);return{read:arg.length,written:buf.length}});function passStringToWasm0(arg,malloc,realloc){if(realloc===undefined){const buf=cachedTextEncoder.encode(arg);const ptr=malloc(buf.length,1)>>>0;getUint8Memory0().subarray(ptr,ptr+buf.length).set(buf);WASM_VECTOR_LEN=buf.length;return ptr}let len=arg.length;let ptr=malloc(len,1)>>>0;const mem=getUint8Memory0();let offset=0;for(;offset0x7F)break;mem[ptr+offset]=code}if(offset!==len){if(offset!==0){arg=arg.slice(offset)}ptr=realloc(ptr,len,len=offset+arg.length*3,1)>>>0;const view=getUint8Memory0().subarray(ptr+offset,ptr+len);const ret=encodeString(arg,view);offset+=ret.written;ptr=realloc(ptr,len,offset,1)>>>0}WASM_VECTOR_LEN=offset;return ptr}__exports.set_ranking_weights=function(ptr,weights){const ptr0=passStringToWasm0(weights,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len0=WASM_VECTOR_LEN;const ret=wasm.set_ranking_weights(ptr,ptr0,len0);return ret>>>0};__exports.load_index_chunk=function(ptr,chunk_bytes){const ptr0=passArray8ToWasm0(chunk_bytes,wasm.__wbindgen_malloc);const len0=WASM_VECTOR_LEN;const ret=wasm.load_index_chunk(ptr,ptr0,len0);return ret>>>0};__exports.load_filter_chunk=function(ptr,chunk_bytes){const ptr0=passArray8ToWasm0(chunk_bytes,wasm.__wbindgen_malloc);const len0=WASM_VECTOR_LEN;const ret=wasm.load_filter_chunk(ptr,ptr0,len0);return ret>>>0};__exports.add_synthetic_filter=function(ptr,filter){const ptr0=passStringToWasm0(filter,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len0=WASM_VECTOR_LEN;const ret=wasm.add_synthetic_filter(ptr,ptr0,len0);return ret>>>0};let cachedInt32Memory0=null;function getInt32Memory0(){if(cachedInt32Memory0===null||cachedInt32Memory0.byteLength===0){cachedInt32Memory0=new Int32Array(wasm.memory.buffer)}return cachedInt32Memory0}const cachedTextDecoder=(typeof TextDecoder!=='undefined'?new TextDecoder('utf-8',{ignoreBOM:true,fatal:true}):{decode:()=>{throw Error('TextDecoder not available')}});if(typeof TextDecoder!=='undefined'){cachedTextDecoder.decode()};function getStringFromWasm0(ptr,len){ptr=ptr>>>0;return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr,ptr+len))}__exports.request_indexes=function(ptr,query){let deferred2_0;let deferred2_1;try{const retptr=wasm.__wbindgen_add_to_stack_pointer(-16);const ptr0=passStringToWasm0(query,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len0=WASM_VECTOR_LEN;wasm.request_indexes(retptr,ptr,ptr0,len0);var r0=getInt32Memory0()[retptr/4+0];var r1=getInt32Memory0()[retptr/4+1];deferred2_0=r0;deferred2_1=r1;return getStringFromWasm0(r0,r1)}finally{wasm.__wbindgen_add_to_stack_pointer(16);wasm.__wbindgen_free(deferred2_0,deferred2_1,1)}};__exports.request_filter_indexes=function(ptr,filters){let deferred2_0;let deferred2_1;try{const retptr=wasm.__wbindgen_add_to_stack_pointer(-16);const ptr0=passStringToWasm0(filters,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len0=WASM_VECTOR_LEN;wasm.request_filter_indexes(retptr,ptr,ptr0,len0);var r0=getInt32Memory0()[retptr/4+0];var r1=getInt32Memory0()[retptr/4+1];deferred2_0=r0;deferred2_1=r1;return getStringFromWasm0(r0,r1)}finally{wasm.__wbindgen_add_to_stack_pointer(16);wasm.__wbindgen_free(deferred2_0,deferred2_1,1)}};__exports.request_all_filter_indexes=function(ptr){let deferred1_0;let deferred1_1;try{const retptr=wasm.__wbindgen_add_to_stack_pointer(-16);wasm.request_all_filter_indexes(retptr,ptr);var r0=getInt32Memory0()[retptr/4+0];var r1=getInt32Memory0()[retptr/4+1];deferred1_0=r0;deferred1_1=r1;return getStringFromWasm0(r0,r1)}finally{wasm.__wbindgen_add_to_stack_pointer(16);wasm.__wbindgen_free(deferred1_0,deferred1_1,1)}};__exports.filters=function(ptr){let deferred1_0;let deferred1_1;try{const retptr=wasm.__wbindgen_add_to_stack_pointer(-16);wasm.filters(retptr,ptr);var r0=getInt32Memory0()[retptr/4+0];var r1=getInt32Memory0()[retptr/4+1];deferred1_0=r0;deferred1_1=r1;return getStringFromWasm0(r0,r1)}finally{wasm.__wbindgen_add_to_stack_pointer(16);wasm.__wbindgen_free(deferred1_0,deferred1_1,1)}};__exports.search=function(ptr,query,filter,sort,exact){let deferred4_0;let deferred4_1;try{const retptr=wasm.__wbindgen_add_to_stack_pointer(-16);const ptr0=passStringToWasm0(query,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len0=WASM_VECTOR_LEN;const ptr1=passStringToWasm0(filter,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;const ptr2=passStringToWasm0(sort,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len2=WASM_VECTOR_LEN;wasm.search(retptr,ptr,ptr0,len0,ptr1,len1,ptr2,len2,exact);var r0=getInt32Memory0()[retptr/4+0];var r1=getInt32Memory0()[retptr/4+1];deferred4_0=r0;deferred4_1=r1;return getStringFromWasm0(r0,r1)}finally{wasm.__wbindgen_add_to_stack_pointer(16);wasm.__wbindgen_free(deferred4_0,deferred4_1,1)}};async function __wbg_load(module,imports){if(typeof Response==='function'&&module instanceof Response){if(typeof WebAssembly.instantiateStreaming==='function'){try{return await WebAssembly.instantiateStreaming(module,imports)}catch(e){if(module.headers.get('Content-Type')!='application/wasm'){console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",e)}else{throw e}}}const bytes=await module.arrayBuffer();return await WebAssembly.instantiate(bytes,imports)}else{const instance=await WebAssembly.instantiate(module,imports);if(instance instanceof WebAssembly.Instance){return{instance,module}}else{return instance}}}function __wbg_get_imports(){const imports={};imports.wbg={};return imports}function __wbg_init_memory(imports,maybe_memory){}function __wbg_finalize_init(instance,module){wasm=instance.exports;__wbg_init.__wbindgen_wasm_module=module;cachedInt32Memory0=null;cachedUint8Memory0=null;return wasm}function initSync(module){if(wasm!==undefined)return wasm;const imports=__wbg_get_imports();__wbg_init_memory(imports);if(!(module instanceof WebAssembly.Module)){module=new WebAssembly.Module(module)}const instance=new WebAssembly.Instance(module,imports);return __wbg_finalize_init(instance,module)}async function __wbg_init(input){if(wasm!==undefined)return wasm;if(typeof input==='undefined'&&typeof script_src!=='undefined'){input=script_src.replace(/\.js$/,'_bg.wasm')}const imports=__wbg_get_imports();if(typeof input==='string'||(typeof Request==='function'&&input instanceof Request)||(typeof URL==='function'&&input instanceof URL)){input=fetch(input)}__wbg_init_memory(imports);const{instance,module}=await __wbg_load(await input,imports);return __wbg_finalize_init(instance,module)}wasm_bindgen=Object.assign(__wbg_init,{initSync},__exports)})();var u8=Uint8Array;var u16=Uint16Array;var u32=Uint32Array;var fleb=new u8([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]);var fdeb=new u8([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]);var clim=new u8([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]);var freb=function(eb,start){var b=new u16(31);for(var i2=0;i2<31;++i2){b[i2]=start+=1<>>1|(i&21845)<<1;x=(x&52428)>>>2|(x&13107)<<2;x=(x&61680)>>>4|(x&3855)<<4;rev[i]=((x&65280)>>>8|(x&255)<<8)>>>1}var x;var i;var hMap=function(cd,mb,r){var s=cd.length;var i2=0;var l=new u16(mb);for(;i2>>rvb]=sv}}}}else{co=new u16(s);for(i2=0;i2>>15-cd[i2]}}}return co};var flt=new u8(288);for(i=0;i<144;++i)flt[i]=8;var i;for(i=144;i<256;++i)flt[i]=9;var i;for(i=256;i<280;++i)flt[i]=7;var i;for(i=280;i<288;++i)flt[i]=8;var i;var fdt=new u8(32);for(i=0;i<32;++i)fdt[i]=5;var i;var flrm=hMap(flt,9,1);var fdrm=hMap(fdt,5,1);var max=function(a){var m=a[0];for(var i2=1;i2m)m=a[i2]}return m};var bits=function(d,p,m){var o=p/8|0;return(d[o]|d[o+1]<<8)>>(p&7)&m};var bits16=function(d,p){var o=p/8|0;return(d[o]|d[o+1]<<8|d[o+2]<<16)>>(p&7)};var shft=function(p){return(p+7)/8|0};var slc=function(v,s,e){if(s==null||s<0)s=0;if(e==null||e>v.length)e=v.length;var n=new(v.BYTES_PER_ELEMENT==2?u16:v.BYTES_PER_ELEMENT==4?u32:u8)(e-s);n.set(v.subarray(s,e));return n};var ec=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"];var err=function(ind,msg,nt){var e=new Error(msg||ec[ind]);e.code=ind;if(Error.captureStackTrace)Error.captureStackTrace(e,err);if(!nt)throw e;return e};var inflt=function(dat,buf,st){var sl=dat.length;if(!sl||st&&st.f&&!st.l)return buf||new u8(0);var noBuf=!buf||st;var noSt=!st||st.i;if(!st)st={};if(!buf)buf=new u8(sl*3);var cbuf=function(l2){var bl=buf.length;if(l2>bl){var nbuf=new u8(Math.max(bl*2,l2));nbuf.set(buf);buf=nbuf}};var final=st.f||0,pos=st.p||0,bt=st.b||0,lm=st.l,dm=st.d,lbt=st.m,dbt=st.n;var tbts=sl*8;do{if(!lm){final=bits(dat,pos,1);var type=bits(dat,pos+1,3);pos+=3;if(!type){var s=shft(pos)+4,l=dat[s-4]|dat[s-3]<<8,t=s+l;if(t>sl){if(noSt)err(0);break}if(noBuf)cbuf(bt+l);buf.set(dat.subarray(s,t),bt);st.b=bt+=l,st.p=pos=t*8,st.f=final;continue}else if(type==1)lm=flrm,dm=fdrm,lbt=9,dbt=5;else if(type==2){var hLit=bits(dat,pos,31)+257,hcLen=bits(dat,pos+10,15)+4;var tl=hLit+bits(dat,pos+5,31)+1;pos+=14;var ldt=new u8(tl);var clt=new u8(19);for(var i2=0;i2>>4;if(s<16){ldt[i2++]=s}else{var c=0,n=0;if(s==16)n=3+bits(dat,pos,3),pos+=2,c=ldt[i2-1];else if(s==17)n=3+bits(dat,pos,7),pos+=3;else if(s==18)n=11+bits(dat,pos,127),pos+=7;while(n--)ldt[i2++]=c}}var lt=ldt.subarray(0,hLit),dt=ldt.subarray(hLit);lbt=max(lt);dbt=max(dt);lm=hMap(lt,lbt,1);dm=hMap(dt,dbt,1)}else err(1);if(pos>tbts){if(noSt)err(0);break}}if(noBuf)cbuf(bt+131072);var lms=(1<>>4;pos+=c&15;if(pos>tbts){if(noSt)err(0);break}if(!c)err(2);if(sym<256)buf[bt++]=sym;else if(sym==256){lpos=pos,lm=null;break}else{var add=sym-254;if(sym>264){var i2=sym-257,b=fleb[i2];add=bits(dat,pos,(1<>>4;if(!d)err(3);pos+=d&15;var dt=fd[dsym];if(dsym>3){var b=fdeb[dsym];dt+=bits16(dat,pos)&(1<tbts){if(noSt)err(0);break}if(noBuf)cbuf(bt+131072);var end=bt+add;for(;bt>3&1)+(flg>>4&1);zs>0;zs-=!d[st++]);return st+(flg&2)};var gzl=function(d){var l=d.length;return(d[l-4]|d[l-3]<<8|d[l-2]<<16|d[l-1]<<24)>>>0};function gunzipSync(data,out){return inflt(data.subarray(gzs(data),-8),out||new u8(gzl(data)))}var td=typeof TextDecoder!="undefined"&&new TextDecoder();var tds=0;try{td.decode(et,{stream:true});tds=1}catch(e){}var gz_default=gunzipSync;var calculate_excerpt_region=(word_positions,excerpt_length)=>{if(word_positions.length===0){return 0}let words=[];for(const word of word_positions){words[word.location]=words[word.location]||0;words[word.location]+=word.balanced_score}if(words.length<=excerpt_length){return 0}let densest=words.slice(0,excerpt_length).reduce((partialSum,a)=>partialSum+a,0);let working_sum=densest;let densest_at=[0];for(let i2=0;i2densest){densest=working_sum;densest_at=[i2]}else if(working_sum===densest&&densest_at[densest_at.length-1]===i2-1){densest_at.push(i2)}}let midpoint=densest_at[Math.floor(densest_at.length/2)];return midpoint};var build_excerpt=(content,start,length,locations,not_before,not_from)=>{let is_zws_delimited=content.includes("\u200B");let fragment_words=[];if(is_zws_delimited){fragment_words=content.split("\u200B")}else{fragment_words=content.split(/[\r\n\s]+/g)}for(let word of locations){if(fragment_words[word]?.startsWith(``)){continue}fragment_words[word]=`${fragment_words[word]}`}let endcap=not_from??fragment_words.length;let startcap=not_before??0;if(endcap-startcapendcap){start=endcap-length}if(start{const anchors=fragment.anchors.filter((a)=>/h\d/i.test(a.element)&&a.text?.length&&/\S/.test(a.text)).sort((a,b)=>a.location-b.location);const results=[];let current_anchor_position=0;let current_anchor={title:fragment.meta["title"],url:fragment.url,weighted_locations:[],locations:[],excerpt:""};const add_result=(end_range)=>{if(current_anchor.locations.length){const relative_weighted_locations=current_anchor.weighted_locations.map((l)=>{return{weight:l.weight,balanced_score:l.balanced_score,location:l.location-current_anchor_position}});const excerpt_start=calculate_excerpt_region(relative_weighted_locations,desired_excerpt_length)+current_anchor_position;const excerpt_length=end_range?Math.min(end_range-excerpt_start,desired_excerpt_length):desired_excerpt_length;current_anchor.excerpt=build_excerpt(fragment.raw_content??"",excerpt_start,excerpt_length,current_anchor.locations,current_anchor_position,end_range);results.push(current_anchor)}};for(let word of fragment.weighted_locations){if(!anchors.length||word.location=anchors[0].location){next_anchor=anchors.shift()}let anchored_url=fragment.url;try{const url_is_fq=/^((https?:)?\/\/)/.test(anchored_url);if(url_is_fq){let fq_url=new URL(anchored_url);fq_url.hash=next_anchor.id;anchored_url=fq_url.toString()}else{if(!/^\//.test(anchored_url)){anchored_url=`/${anchored_url}`}let fq_url=new URL(`https://example.com${anchored_url}`);fq_url.hash=next_anchor.id;anchored_url=fq_url.toString().replace(/^https:\/\/example.com/,"")}}catch(e){console.error(`Pagefind: Couldn't process ${anchored_url} for a search result`)}current_anchor_position=next_anchor.location;current_anchor={title:next_anchor.text,url:anchored_url,anchor:next_anchor,weighted_locations:[word],locations:[word.location],excerpt:""}}}add_result(anchors[0]?.location);return results};var asyncSleep=async(ms=100)=>{return new Promise((r)=>setTimeout(r,ms))};var PagefindInstance=class{constructor(opts={}){this.version=pagefind_version;this.backend=wasm_bindgen;this.decoder=new TextDecoder("utf-8");this.wasm=null;this.basePath=opts.basePath||"/pagefind/";this.primary=opts.primary||false;if(this.primary&&!opts.basePath){this.initPrimary()}if(/[^\/]$/.test(this.basePath)){this.basePath=`${this.basePath}/`}if(window?.location?.origin&&this.basePath.startsWith(window.location.origin)){this.basePath=this.basePath.replace(window.location.origin,"")}this.baseUrl=opts.baseUrl||this.defaultBaseUrl();if(!/^(\/|https?:\/\/)/.test(this.baseUrl)){this.baseUrl=`/${this.baseUrl}`}this.indexWeight=opts.indexWeight??1;this.excerptLength=opts.excerptLength??30;this.mergeFilter=opts.mergeFilter??{};this.ranking=opts.ranking;this.highlightParam=opts.highlightParam??null;this.loaded_chunks={};this.loaded_filters={};this.loaded_fragments={};this.raw_ptr=null;this.searchMeta=null;this.languages=null}initPrimary(){let derivedBasePath=import.meta.url.match(/^(.*\/)pagefind.js.*$/)?.[1];if(derivedBasePath){this.basePath=derivedBasePath}else{console.warn(["Pagefind couldn't determine the base of the bundle from the import path. Falling back to the default.","Set a basePath option when initialising Pagefind to ignore this message."].join("\n"))}}defaultBaseUrl(){let default_base=this.basePath.match(/^(.*\/)_?pagefind/)?.[1];return default_base||"/"}async options(options2){const opts=["basePath","baseUrl","indexWeight","excerptLength","mergeFilter","highlightParam","ranking"];for(const[k,v]of Object.entries(options2)){if(k==="mergeFilter"){let filters2=this.stringifyFilters(v);let ptr=await this.getPtr();this.raw_ptr=this.backend.add_synthetic_filter(ptr,filters2)}else if(k==="ranking"){await this.set_ranking(options2.ranking)}else if(opts.includes(k)){if(k==="basePath"&&typeof v==="string")this.basePath=v;if(k==="baseUrl"&&typeof v==="string")this.baseUrl=v;if(k==="indexWeight"&&typeof v==="number")this.indexWeight=v;if(k==="excerptLength"&&typeof v==="number")this.excerptLength=v;if(k==="mergeFilter"&&typeof v==="object")this.mergeFilter=v;if(k==="highlightParam"&&typeof v==="string")this.highlightParam=v}else{console.warn(`Unknown Pagefind option ${k}. Allowed options: [${opts.join(", ")}]`)}}}decompress(data,file="unknown file"){if(this.decoder.decode(data.slice(0,12))==="pagefind_dcd"){return data.slice(12)}data=gz_default(data);if(this.decoder.decode(data.slice(0,12))!=="pagefind_dcd"){console.error(`Decompressing ${file} appears to have failed: Missing signature`);return data}return data.slice(12)}async set_ranking(ranking){if(!ranking)return;let rankingWeights={term_similarity:ranking.termSimilarity??null,page_length:ranking.pageLength??null,term_saturation:ranking.termSaturation??null,term_frequency:ranking.termFrequency??null};let ptr=await this.getPtr();this.raw_ptr=this.backend.set_ranking_weights(ptr,JSON.stringify(rankingWeights))}async init(language,opts){await this.loadEntry();let index=this.findIndex(language);let lang_wasm=index.wasm?index.wasm:"unknown";let resources=[this.loadMeta(index.hash)];if(opts.load_wasm===true){resources.push(this.loadWasm(lang_wasm))}await Promise.all(resources);this.raw_ptr=this.backend.init_pagefind(new Uint8Array(this.searchMeta));if(Object.keys(this.mergeFilter)?.length){let filters2=this.stringifyFilters(this.mergeFilter);let ptr=await this.getPtr();this.raw_ptr=this.backend.add_synthetic_filter(ptr,filters2)}if(this.ranking){await this.set_ranking(this.ranking)}}async loadEntry(){try{let entry_response=await fetch(`${this.basePath}pagefind-entry.json?ts=${Date.now()}`);let entry_json=await entry_response.json();this.languages=entry_json.languages;if(entry_json.version!==this.version){if(this.primary){console.warn(["Pagefind JS version doesn't match the version in your search index.",`Pagefind JS: ${this.version}. Pagefind index: ${entry_json.version}`,"If you upgraded Pagefind recently, you likely have a cached pagefind.js file.","If you encounter any search errors, try clearing your cache."].join("\n"))}else{console.warn(["Merging a Pagefind index from a different version than the main Pagefind instance.",`Main Pagefind JS: ${this.version}. Merged index (${this.basePath}): ${entry_json.version}`,"If you encounter any search errors, make sure that both sites are running the same version of Pagefind."].join("\n"))}}}catch(e){console.error(`Failed to load Pagefind metadata: +${e?.toString()}`);throw new Error("Failed to load Pagefind metadata")}}findIndex(language){if(this.languages){let index=this.languages[language];if(index)return index;index=this.languages[language.split("-")[0]];if(index)return index;let topLang=Object.values(this.languages).sort((a,b)=>b.page_count-a.page_count);if(topLang[0])return topLang[0]}throw new Error("Pagefind Error: No language indexes found.")}async loadMeta(index){try{let compressed_resp=await fetch(`${this.basePath}pagefind.${index}.pf_meta`);let compressed_meta=await compressed_resp.arrayBuffer();this.searchMeta=this.decompress(new Uint8Array(compressed_meta),"Pagefind metadata")}catch(e){console.error(`Failed to load the meta index: +${e?.toString()}`)}}async loadWasm(language){try{const wasm_url=`${this.basePath}wasm.${language}.pagefind`;let compressed_resp=await fetch(wasm_url);let compressed_wasm=await compressed_resp.arrayBuffer();const final_wasm=this.decompress(new Uint8Array(compressed_wasm),"Pagefind WebAssembly");if(!final_wasm){throw new Error("No WASM after decompression")}this.wasm=await this.backend(final_wasm)}catch(e){console.error(`Failed to load the Pagefind WASM: +${e?.toString()}`);throw new Error(`Failed to load the Pagefind WASM: +${e?.toString()}`)}}async _loadGenericChunk(url,method){try{let compressed_resp=await fetch(url);let compressed_chunk=await compressed_resp.arrayBuffer();let chunk=this.decompress(new Uint8Array(compressed_chunk),url);let ptr=await this.getPtr();this.raw_ptr=this.backend[method](ptr,chunk)}catch(e){console.error(`Failed to load the index chunk ${url}: +${e?.toString()}`)}}async loadChunk(hash){if(!this.loaded_chunks[hash]){const url=`${this.basePath}index/${hash}.pf_index`;this.loaded_chunks[hash]=this._loadGenericChunk(url,"load_index_chunk")}return await this.loaded_chunks[hash]}async loadFilterChunk(hash){if(!this.loaded_filters[hash]){const url=`${this.basePath}filter/${hash}.pf_filter`;this.loaded_filters[hash]=this._loadGenericChunk(url,"load_filter_chunk")}return await this.loaded_filters[hash]}async _loadFragment(hash){let compressed_resp=await fetch(`${this.basePath}fragment/${hash}.pf_fragment`);let compressed_fragment=await compressed_resp.arrayBuffer();let fragment=this.decompress(new Uint8Array(compressed_fragment),`Fragment ${hash}`);return JSON.parse(new TextDecoder().decode(fragment))}async loadFragment(hash,weighted_locations=[],search_term){if(!this.loaded_fragments[hash]){this.loaded_fragments[hash]=this._loadFragment(hash)}let fragment=await this.loaded_fragments[hash];fragment.weighted_locations=weighted_locations;fragment.locations=weighted_locations.map((l)=>l.location);if(!fragment.raw_content){fragment.raw_content=fragment.content.replace(//g,">");fragment.content=fragment.content.replace(/\u200B/g,"")}if(!fragment.raw_url){fragment.raw_url=fragment.url}fragment.url=this.processedUrl(fragment.raw_url,search_term);const excerpt_start=calculate_excerpt_region(weighted_locations,this.excerptLength);fragment.excerpt=build_excerpt(fragment.raw_content,excerpt_start,this.excerptLength,fragment.locations);fragment.sub_results=calculate_sub_results(fragment,this.excerptLength);return fragment}fullUrl(raw){if(/^(https?:)?\/\//.test(raw)){return raw}return`${this.baseUrl}/${raw}`.replace(/\/+/g,"/").replace(/^(https?:\/)/,"$1/")}processedUrl(url,search_term){const normalized=this.fullUrl(url);if(this.highlightParam===null){return normalized}let individual_terms=search_term.split(/\s+/);try{let processed=new URL(normalized);for(const term of individual_terms){processed.searchParams.append(this.highlightParam,term)}return processed.toString()}catch(e){try{let processed=new URL(`https://example.com${normalized}`);for(const term of individual_terms){processed.searchParams.append(this.highlightParam,term)}return processed.toString().replace(/^https:\/\/example\.com/,"")}catch(e2){return normalized}}}async getPtr(){while(this.raw_ptr===null){await asyncSleep(50)}if(!this.raw_ptr){console.error("Pagefind: WASM Error (No pointer)");throw new Error("Pagefind: WASM Error (No pointer)")}return this.raw_ptr}parseFilters(str){let output={};if(!str)return output;for(const block of str.split("__PF_FILTER_DELIM__")){let[filter,values]=block.split(/:(.*)$/);output[filter]={};if(values){for(const valueBlock of values.split("__PF_VALUE_DELIM__")){if(valueBlock){let extract=valueBlock.match(/^(.*):(\d+)$/);if(extract){let[,value,count]=extract;output[filter][value]=parseInt(count)??count}}}}}return output}stringifyFilters(obj={}){return JSON.stringify(obj)}stringifySorts(obj={}){let sorts=Object.entries(obj);for(let[sort,direction]of sorts){if(sorts.length>1){console.warn(`Pagefind was provided multiple sort options in this search, but can only operate on one. Using the ${sort} sort.`)}if(direction!=="asc"&&direction!=="desc"){console.warn(`Pagefind was provided a sort with unknown direction ${direction}. Supported: [asc, desc]`)}return`${sort}:${direction}`}return``}async filters(){let ptr=await this.getPtr();let filters2=this.backend.request_all_filter_indexes(ptr);let filter_chunks=filters2.split(" ").filter((v)=>v).map((chunk)=>this.loadFilterChunk(chunk));await Promise.all([...filter_chunks]);ptr=await this.getPtr();let results=this.backend.filters(ptr);return this.parseFilters(results)}async preload(term,options2={}){await this.search(term,{...options2,preload:true})}async search(term,options2={}){options2={verbose:false,filters:{},sort:{},...options2};const log=(str)=>{if(options2.verbose)console.log(str)};log(`Starting search on ${this.basePath}`);let start=Date.now();let ptr=await this.getPtr();let filter_only=term===null;term=term??"";let exact_search=/^\s*".+"\s*$/.test(term);if(exact_search){log(`Running an exact search`)}term=term.toLowerCase().trim().replace(/[\.`~!@#\$%\^&\*\(\)\{\}\[\]\\\|:;'",<>\/\?\-]/g,"").replace(/\s{2,}/g," ").trim();log(`Normalized search term to ${term}`);if(!term?.length&&!filter_only){return{results:[],unfilteredResultCount:0,filters:{},totalFilters:{},timings:{preload:Date.now()-start,search:Date.now()-start,total:Date.now()-start}}}let sort_list=this.stringifySorts(options2.sort);log(`Stringified sort to ${sort_list}`);const filter_list=this.stringifyFilters(options2.filters);log(`Stringified filters to ${filter_list}`);let index_resp=this.backend.request_indexes(ptr,term);let filter_resp=this.backend.request_filter_indexes(ptr,filter_list);let chunks=index_resp.split(" ").filter((v)=>v).map((chunk)=>this.loadChunk(chunk));let filter_chunks=filter_resp.split(" ").filter((v)=>v).map((chunk)=>this.loadFilterChunk(chunk));await Promise.all([...chunks,...filter_chunks]);log(`Loaded necessary chunks to run search`);if(options2.preload){log(`Preload \u2014 bailing out of search operation now.`);return null}ptr=await this.getPtr();let searchStart=Date.now();let result=this.backend.search(ptr,term,filter_list,sort_list,exact_search);log(`Got the raw search result: ${result}`);let[unfilteredResultCount,all_results,filters2,totalFilters]=result.split(/:([^:]*):(.*)__PF_UNFILTERED_DELIM__(.*)$/);let filterObj=this.parseFilters(filters2);let totalFilterObj=this.parseFilters(totalFilters);log(`Remaining filters: ${JSON.stringify(result)}`);let results=all_results.length?all_results.split(" "):[];let resultsInterface=results.map((result2)=>{let[hash,score,all_locations]=result2.split("@");log(`Processing result: + hash:${hash} + score:${score} + locations:${all_locations}`);let weighted_locations=all_locations.length?all_locations.split(",").map((l)=>{let[weight,balanced_score,location]=l.split(">");return{weight:parseInt(weight)/24,balanced_score:parseFloat(balanced_score),location:parseInt(location)}}):[];let locations=weighted_locations.map((l)=>l.location);return{id:hash,score:parseFloat(score)*this.indexWeight,words:locations,data:async()=>await this.loadFragment(hash,weighted_locations,term)}});const searchTime=Date.now()-searchStart;const realTime=Date.now()-start;log(`Found ${results.length} result${results.length == 1 ? "" : "s"} for "${term}" in ${Date.now() - searchStart}ms (${Date.now() - start}ms realtime)`);return{results:resultsInterface,unfilteredResultCount:parseInt(unfilteredResultCount),filters:filterObj,totalFilters:totalFilterObj,timings:{preload:realTime-searchTime,search:searchTime,total:realTime}}}};var Pagefind=class{constructor(options2={}){this.backend=wasm_bindgen;this.primaryLanguage="unknown";this.searchID=0;this.primary=new PagefindInstance({...options2,primary:true});this.instances=[this.primary];this.init(options2?.language)}async options(options2){await this.primary.options(options2)}async init(overrideLanguage){if(document?.querySelector){const langCode=document.querySelector("html")?.getAttribute("lang")||"unknown";this.primaryLanguage=langCode.toLocaleLowerCase()}await this.primary.init(overrideLanguage?overrideLanguage:this.primaryLanguage,{load_wasm:true})}async mergeIndex(indexPath,options2={}){if(this.primary.basePath.startsWith(indexPath)){console.warn(`Skipping mergeIndex ${indexPath} that appears to be the same as the primary index (${this.primary.basePath})`);return}let newInstance=new PagefindInstance({primary:false,basePath:indexPath});this.instances.push(newInstance);while(this.primary.wasm===null){await asyncSleep(50)}await newInstance.init(options2.language||this.primaryLanguage,{load_wasm:false});delete options2["language"];await newInstance.options(options2)}mergeFilters(filters2){const merged={};for(const searchFilter of filters2){for(const[filterKey,values]of Object.entries(searchFilter)){if(!merged[filterKey]){merged[filterKey]=values;continue}else{const filter=merged[filterKey];for(const[valueKey,count]of Object.entries(values)){filter[valueKey]=(filter[valueKey]||0)+count}}}}return merged}async filters(){let filters2=await Promise.all(this.instances.map((i2)=>i2.filters()));return this.mergeFilters(filters2)}async preload(term,options2={}){await Promise.all(this.instances.map((i2)=>i2.preload(term,options2)))}async debouncedSearch(term,options2,debounceTimeoutMs){const thisSearchID=++this.searchID;this.preload(term,options2);await asyncSleep(debounceTimeoutMs);if(thisSearchID!==this.searchID){return null}const searchResult=await this.search(term,options2);if(thisSearchID!==this.searchID){return null}return searchResult}async search(term,options2={}){let search2=await Promise.all(this.instances.map((i2)=>i2.search(term,options2)));const filters2=this.mergeFilters(search2.map((s)=>s.filters));const totalFilters=this.mergeFilters(search2.map((s)=>s.totalFilters));const results=search2.map((s)=>s.results).flat().sort((a,b)=>b.score-a.score);const timings=search2.map((s)=>s.timings);const unfilteredResultCount=search2.reduce((sum,s)=>sum+s.unfilteredResultCount,0);return{results,unfilteredResultCount,filters:filters2,totalFilters,timings}}};var pagefind=void 0;var initial_options=void 0;var init_pagefind=()=>{if(!pagefind){pagefind=new Pagefind(initial_options??{})}};var options=async(new_options)=>{if(pagefind){await pagefind.options(new_options)}else{initial_options=new_options}};var init=async()=>{init_pagefind()};var destroy=async()=>{pagefind=void 0;initial_options=void 0};var mergeIndex=async(indexPath,options2)=>{init_pagefind();return await pagefind.mergeIndex(indexPath,options2)};var search=async(term,options2)=>{init_pagefind();return await pagefind.search(term,options2)};var debouncedSearch=async(term,options2,debounceTimeoutMs=300)=>{init_pagefind();return await pagefind.debouncedSearch(term,options2,debounceTimeoutMs)};var preload=async(term,options2)=>{init_pagefind();return await pagefind.preload(term,options2)};var filters=async()=>{init_pagefind();return await pagefind.filters()};export{debouncedSearch,destroy,filters,init,mergeIndex,options,preload,search} \ No newline at end of file diff --git a/public/pagefind/wasm.en.pagefind b/public/pagefind/wasm.en.pagefind new file mode 100644 index 0000000..6a6c03e Binary files /dev/null and b/public/pagefind/wasm.en.pagefind differ diff --git a/public/pagefind/wasm.unknown.pagefind b/public/pagefind/wasm.unknown.pagefind new file mode 100644 index 0000000..c9b1460 Binary files /dev/null and b/public/pagefind/wasm.unknown.pagefind differ diff --git a/public/pagination.css b/public/pagination.css new file mode 100644 index 0000000..defd6c0 --- /dev/null +++ b/public/pagination.css @@ -0,0 +1 @@ +.pagination{margin-top:50px}.pagination__title{display:flex;text-align:center;position:relative;margin:100px 0 20px}.pagination__title-h{text-align:center;margin:0 auto;padding:5px 10px;background:var(--background);font-size:.8rem;text-transform:uppercase;letter-spacing:.1em;z-index:1}.pagination__title hr{position:absolute;left:0;right:0;width:100%;margin-top:15px;z-index:0}.pagination__buttons{display:flex;align-items:center;justify-content:center}@media (max-width: 683px){.pagination__buttons{flex-direction:column}}.button{position:relative;display:inline-flex;align-items:center;justify-content:center;font-size:1rem;border-radius:8px;max-width:40%;padding:0;cursor:pointer;appearance:none}@media (max-width: 683px){.button{max-width:80%}}.button+.button{margin-left:10px}.button a{display:flex;padding:8px 16px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.button__text{text-overflow:ellipsis;white-space:nowrap;overflow:hidden} \ No newline at end of file diff --git a/public/post.css b/public/post.css new file mode 100644 index 0000000..2d8fd20 --- /dev/null +++ b/public/post.css @@ -0,0 +1 @@ +.posts{width:100%;margin:0 auto}.post{width:100%;text-align:left;margin:20px auto;padding:20px 0}@media (max-width: 899px){.post{max-width:660px}}.post:not(:last-of-type){border-bottom:1px solid var(--border-color)}.post .post-meta-inline,.post .post-meta{font-size:1rem;margin-bottom:10px;color:var(--accent-alpha-70)}.post-meta-inline{display:inline}.post-title{--border: 2px dashed var(--accent);position:relative;color:var(--accent);margin:0 0 15px;padding-bottom:15px;border-bottom:var(--border);font-weight:normal}.post-title a{text-decoration:none}.post .post-tags-inline,.post .post-tags{margin-bottom:20px;font-size:1rem;opacity:.5}.post-tags{display:block}.post-tags-inline{display:inline}@media (max-width: 683px){.post-tags-inline{display:block}}.post-content{margin-top:30px}.post-cover{border:20px solid var(--accent);background:rgba(0,0,0,0);margin:40px 0;padding:20px}@media (max-width: 683px){.post-cover{padding:10px;border-width:10px}}.post ul{list-style:none}.post ul li:before{content:"►";position:absolute;left:-20px;color:var(--accent)}.post--regulation h1{justify-content:center}.post--regulation h2{justify-content:center;margin-bottom:10px}.post--regulation h2+h2{margin-top:-10px;margin-bottom:20px}.post-list .post-date{color:var(--accent-alpha-70);text-decoration:none}.post-list a{text-decoration:none}.post-list .post-list-title{text-decoration:underline}.post-list .post-tag{text-decoration:underline} \ No newline at end of file diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..cfb5334 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Disallow: +Allow: / +Sitemap: https://blog.dich.bid/sitemap.xml diff --git a/public/rss-style.xslt b/public/rss-style.xslt new file mode 100755 index 0000000..def26a6 --- /dev/null +++ b/public/rss-style.xslt @@ -0,0 +1,60 @@ + + + + + + + + + <xsl:value-of select="/atom:feed/atom:title"/> + + + +

    + +

    + +

    + +

    + +

    + This is the Atom news feed for the + + + + + website. +

    +

    It is meant for news readers, not humans. Please copy-and-paste the URL into your news reader!

    +

    + +

    + +
    + + + + + +  -  + + + + + + + + + + +
    +
    +

    news items.

    +

    Powered by Feed.Style

    + + +
    +
    \ No newline at end of file diff --git a/public/search/index.html b/public/search/index.html new file mode 100644 index 0000000..81f18da --- /dev/null +++ b/public/search/index.html @@ -0,0 +1,134 @@ + + + + + +Search | Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + +
    + + +
    + + + + + + + +
    + + +
    + +
    + +
    + + + diff --git a/public/sitemap.xml b/public/sitemap.xml new file mode 100644 index 0000000..b5053e8 --- /dev/null +++ b/public/sitemap.xml @@ -0,0 +1,385 @@ + + + + https://blog.dich.bid/ + + + https://blog.dich.bid/about-2024/ + 2025-01-04 + + + https://blog.dich.bid/about-accurate-pronunciation/ + 2023-08-25 + + + https://blog.dich.bid/about-aria2/ + 2025-04-15 + + + https://blog.dich.bid/about-baci/ + 2025-04-23 + + + https://blog.dich.bid/about-blog/ + 2023-10-12 + + + https://blog.dich.bid/about-calling-cards/ + 2023-08-24 + + + https://blog.dich.bid/about-cslearning/ + 2024-05-31 + + + https://blog.dich.bid/about-frp/ + 2025-03-01 + + + https://blog.dich.bid/about-gfs/ + 2025-03-18 + + + https://blog.dich.bid/about-git/ + 2023-12-15 + + + https://blog.dich.bid/about-gpg/ + 2025-06-17 + + + https://blog.dich.bid/about-junk-cleanup/ + 2023-11-19 + + + https://blog.dich.bid/about-lazyvim/ + 2025-04-20 + + + https://blog.dich.bid/about-markdown/ + 2025-04-08 + + + https://blog.dich.bid/about-mechrev-keyboard/ + 2023-09-04 + + + https://blog.dich.bid/about-opensource/ + 2024-03-03 + + + https://blog.dich.bid/about-podcast-use/ + 2024-03-06 + + + https://blog.dich.bid/about-rss-read/ + 2024-03-05 + + + https://blog.dich.bid/about-runer-1/ + 2024-06-08 + + + https://blog.dich.bid/about-runer-2/ + 2024-06-11 + + + https://blog.dich.bid/about-server-set/ + 2024-06-12 + + + https://blog.dich.bid/about-shortcut-key/ + 2024-05-23 + + + https://blog.dich.bid/about-ventoy/ + 2025-02-14 + + + https://blog.dich.bid/about-vim/ + 2024-08-15 + + + https://blog.dich.bid/about/ + + + https://blog.dich.bid/archive/ + + + https://blog.dich.bid/awesome-android-root/ + 2023-08-13 + + + https://blog.dich.bid/awesome-android-tv/ + 2023-08-14 + + + https://blog.dich.bid/awesome-arch-linux/ + 2023-08-16 + + + https://blog.dich.bid/awesome-openwrt/ + 2023-08-12 + + + https://blog.dich.bid/awesome-pve-mcsm/ + 2023-08-11 + + + https://blog.dich.bid/awesome-vm-android/ + 2023-08-10 + + + https://blog.dich.bid/learn-linux-for-pc-1/ + 2023-07-20 + + + https://blog.dich.bid/learn-linux-for-pc-2/ + 2023-07-21 + + + https://blog.dich.bid/learn-linux-for-pc-3/ + 2023-07-22 + + + https://blog.dich.bid/learn-linux-for-pc-4/ + 2023-07-23 + + + https://blog.dich.bid/learn-linux-for-pc-5/ + 2023-07-24 + + + https://blog.dich.bid/learn-linux-for-pc-6/ + 2023-07-25 + + + https://blog.dich.bid/learn-linux-for-pc-7/ + 2023-08-01 + + + https://blog.dich.bid/links/ + + + https://blog.dich.bid/links/link-1/ + + + https://blog.dich.bid/links/link-2/ + + + https://blog.dich.bid/links/link-3/ + + + https://blog.dich.bid/links/link-4/ + + + https://blog.dich.bid/links/link-5/ + + + https://blog.dich.bid/links/link-6/ + + + https://blog.dich.bid/network-cdn/ + 2024-02-16 + + + https://blog.dich.bid/network-download-1/ + 2024-02-09 + + + https://blog.dich.bid/network-how-email-works-1/ + 2024-02-20 + + + https://blog.dich.bid/network-how-email-works-2/ + 2024-02-21 + + + https://blog.dich.bid/network-how-email-works-3/ + 2024-02-22 + + + https://blog.dich.bid/network-isps/ + 2024-02-10 + + + https://blog.dich.bid/network-nginx/ + 2024-07-14 + + + https://blog.dich.bid/network-ssl/ + 2024-02-15 + + + https://blog.dich.bid/network-zuwang/ + 2025-01-21 + + + https://blog.dich.bid/page/1/ + + + https://blog.dich.bid/page/10/ + + + https://blog.dich.bid/page/11/ + + + https://blog.dich.bid/page/2/ + + + https://blog.dich.bid/page/3/ + + + https://blog.dich.bid/page/4/ + + + https://blog.dich.bid/page/5/ + + + https://blog.dich.bid/page/6/ + + + https://blog.dich.bid/page/7/ + + + https://blog.dich.bid/page/8/ + + + https://blog.dich.bid/page/9/ + + + https://blog.dich.bid/search/ + + + https://blog.dich.bid/tags/ + + + https://blog.dich.bid/tags/linux/ + + + https://blog.dich.bid/tags/luan-qi-ba-zao/ + + + https://blog.dich.bid/tags/tan-tian-shuo-di/ + + + https://blog.dich.bid/tags/wang-luo-yi-shu/ + + + https://blog.dich.bid/tags/windows/ + + + https://blog.dich.bid/tags/zong-he-gong-cheng/ + + + https://blog.dich.bid/weekly/ + + + https://blog.dich.bid/weekly/zhoubao-1/ + 2024-06-13 + + + https://blog.dich.bid/weekly/zhoubao-10/ + 2024-08-15 + + + https://blog.dich.bid/weekly/zhoubao-11/ + 2024-08-22 + + + https://blog.dich.bid/weekly/zhoubao-12/ + 2024-08-29 + + + https://blog.dich.bid/weekly/zhoubao-13/ + 2024-09-07 + + + https://blog.dich.bid/weekly/zhoubao-14/ + 2024-09-16 + + + https://blog.dich.bid/weekly/zhoubao-15/ + 2024-09-21 + + + https://blog.dich.bid/weekly/zhoubao-16/ + 2024-09-28 + + + https://blog.dich.bid/weekly/zhoubao-17/ + 2024-10-05 + + + https://blog.dich.bid/weekly/zhoubao-18/ + 2024-10-13 + + + https://blog.dich.bid/weekly/zhoubao-19/ + 2024-10-23 + + + https://blog.dich.bid/weekly/zhoubao-2/ + 2024-06-20 + + + https://blog.dich.bid/weekly/zhoubao-20/ + 2025-01-25 + + + https://blog.dich.bid/weekly/zhoubao-21/ + 2025-02-04 + + + https://blog.dich.bid/weekly/zhoubao-3/ + 2024-06-26 + + + https://blog.dich.bid/weekly/zhoubao-4/ + 2024-07-04 + + + https://blog.dich.bid/weekly/zhoubao-5/ + 2024-07-11 + + + https://blog.dich.bid/weekly/zhoubao-6/ + 2024-07-18 + + + https://blog.dich.bid/weekly/zhoubao-7/ + 2024-07-26 + + + https://blog.dich.bid/weekly/zhoubao-8/ + 2024-08-03 + + + https://blog.dich.bid/weekly/zhoubao-9/ + 2024-08-08 + + + https://blog.dich.bid/windows-activation/ + 2024-05-25 + + + https://blog.dich.bid/windows-all/ + 2024-05-26 + + + https://blog.dich.bid/windows-conda-python/ + 2024-05-31 + + + https://blog.dich.bid/windows-iso/ + 2024-05-29 + + + https://blog.dich.bid/windows-some-setting/ + 2024-05-24 + + + https://blog.dich.bid/windows-vscode-gcc/ + 2024-05-30 + + diff --git a/public/style.css b/public/style.css new file mode 100644 index 0000000..d51f5f1 --- /dev/null +++ b/public/style.css @@ -0,0 +1 @@ +.button-container{display:table;margin-left:auto;margin-right:auto}button,.button,a.button{position:relative;display:flex;align-items:center;justify-content:center;padding:8px 18px;margin-bottom:5px;text-align:center;border-radius:8px;border:1px solid rgba(0,0,0,0);appearance:none;cursor:pointer;outline:none;}button.outline,.button.outline,a.button.outline{background:rgba(0,0,0,0);box-shadow:none;padding:8px 18px}button.outline :hover,.button.outline :hover,a.button.outline :hover{transform:none;box-shadow:none}button.primary,.button.primary,a.button.primary{box-shadow:0 4px 6px rgba(50,50,93,.11),0 1px 3px rgba(0,0,0,.08)}button.primary:hover,.button.primary:hover,a.button.primary:hover{box-shadow:0 2px 6px rgba(50,50,93,.21),0 1px 3px rgba(0,0,0,.08)}button.link,.button.link,a.button.link{background:none;font-size:1rem}button.small,.button.small,a.button.small{font-size:.8rem}button.wide,.button.wide,a.button.wide{min-width:200px;padding:14px 24px}a.read-more,a.read-more:hover,a.read-more:active{display:inline-flex;background:none;box-shadow:none;padding:0;margin:20px 0;max-width:100%}.code-toolbar{margin-bottom:20px}.code-toolbar .toolbar-item a{position:relative;display:inline-flex;align-items:center;justify-content:center;padding:3px 8px;margin-bottom:5px;text-align:center;font-size:13px;font-weight:500;border-radius:8px;border:1px solid rgba(0,0,0,0);appearance:none;cursor:pointer;outline:none}.header{display:flex;flex-direction:column;position:relative}.header__inner{display:flex;align-items:center;justify-content:space-between}.header__logo{display:flex;flex:1}.header__logo:after{content:"";background:repeating-linear-gradient(90deg, var(--accent), var(--accent) 2px, rgba(0,0,0,0) 0, rgba(0,0,0,0) 16px);display:block;width:100%;right:10px}.header__logo a{flex:0 0 auto;max-width:100%}.header .menu{margin:20px 0}.header .menu__inner{display:flex;flex-wrap:wrap;list-style:none;margin:0;padding:0}.header .menu__inner li.active{color:var(--accent-alpha-70)}.header .menu__inner li:not(:last-of-type){margin-right:20px;margin-bottom:10px;flex:0 0 auto}.header .menu__sub-inner{position:relative;list-style:none;padding:0;margin:0}.header .menu__sub-inner:not(:only-child){margin-left:20px}.header .menu__sub-inner-more{position:absolute;background:var(--background);box-shadow:var(--shadow);color:#fff;border:2px solid;margin:0;padding:10px;list-style:none;z-index:99;top:35px;left:0}.header .menu__sub-inner-more-trigger{color:var(--accent);user-select:none;cursor:pointer}.header .menu__sub-inner-more li{margin:0;padding:5px;white-space:nowrap}.logo{display:flex;align-items:center;text-decoration:none;background:var(--accent);color:#000;padding:5px 10px}html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit}body{margin:0;padding:0;font-family:Hack,DejaVu Sans Mono,Monaco,Consolas,Ubuntu Mono,monospace;font-size:1rem;line-height:1.54;background-color:var(--background);color:var(--color);text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-webkit-overflow-scrolling:touch;-webkit-text-size-adjust:100%}@media (max-width: 683px){body{font-size:1rem}}h1,h2,h3,h4,h5,h6{display:flex;align-items:center;font-weight:bold;line-height:1.3}h1{font-size:1.4rem}h2{font-size:1.3rem}h3{font-size:1.2rem}h4,h5,h6{font-size:1.15rem}a{color:inherit}img{display:block;max-width:100%}img.left{margin-right:auto}img.center{margin-left:auto;margin-right:auto}img.right{margin-left:auto}p{margin-bottom:20px}figure{display:table;max-width:100%;margin:25px 0}figure.left,figure img{margin-right:auto}figure.center,figure img{margin-left:auto;margin-right:auto}figure.right,figure img{margin-left:auto}figure figcaption{font-size:14px;padding:5px 10px;margin-top:5px;background:var(--accent);color:var(--background)}figure figcaption.left{text-align:left}figure figcaption.center{text-align:center}figure figcaption.right{text-align:right}code{font-family:Hack,DejaVu Sans Mono,Monaco,Consolas,Ubuntu Mono,monospace;font-feature-settings:normal;background:var(--accent-alpha-20);padding:1px 6px;margin:0 2px;font-size:.95rem}pre{font-family:Hack,DejaVu Sans Mono,Monaco,Consolas,Ubuntu Mono,monospace;padding:20px;font-size:.95rem;overflow:auto;border-top:1px solid rgba(255,255,255,.1);border-bottom:1px solid rgba(255,255,255,.1)}@media (max-width: 683px){pre{white-space:pre-wrap;word-wrap:break-word}}pre code{padding:0;margin:0;background:none}blockquote{border-top:1px solid var(--accent);border-bottom:1px solid var(--accent);margin:40px 0;padding:25px}@media (max-width: 683px){blockquote{padding-right:0}}blockquote:before{content:"”";font-family:Georgia,serif;font-size:3.875rem;position:absolute;left:-40px;top:-20px}blockquote p:first-of-type{margin-top:0}blockquote p:last-of-type{margin-bottom:0}blockquote p{position:relative}blockquote p:before{content:">";display:block;position:absolute;left:-25px;color:var(--accent)}table{table-layout:fixed;border-collapse:collapse;width:100%;margin:40px 0}table,th,td{border:1px dashed var(--accent);padding:10px}th{color:var(--accent)}ul,ol{margin-left:30px;padding:0}ul li,ol li{position:relative}@media (max-width: 683px){ul,ol{margin-left:20px}}ol ol{list-style-type:lower-alpha}.container{display:flex;flex-direction:column;padding:40px;max-width:864px;min-height:100vh;margin:0 auto}@media (max-width: 683px){.container{padding:20px}}.content{display:flex}hr{width:100%;border:none;background:var(--border-color);height:1px}.hidden{display:none}.posts{width:100%;margin:0 auto}.post{width:100%;text-align:left;margin:20px auto;padding:20px 0}@media (max-width: 899px){.post{max-width:660px}}.post:not(:last-of-type){border-bottom:1px solid var(--border-color)}.post .post-meta-inline,.post .post-meta{font-size:1rem;margin-bottom:10px;color:var(--accent-alpha-70)}.post-meta-inline{display:inline}.post-title{--border: 2px dashed var(--accent);position:relative;color:var(--accent);margin:0 0 15px;padding-bottom:15px;border-bottom:var(--border);font-weight:normal}.post-title a{text-decoration:none}.post .post-tags-inline,.post .post-tags{margin-bottom:20px;font-size:1rem;opacity:.5}.post-tags{display:block}.post-tags-inline{display:inline}@media (max-width: 683px){.post-tags-inline{display:block}}.post-content{margin-top:30px}.post-cover{border:20px solid var(--accent);background:rgba(0,0,0,0);margin:40px 0;padding:20px}@media (max-width: 683px){.post-cover{padding:10px;border-width:10px}}.post ul{list-style:none}.post ul li:before{content:"►";position:absolute;left:-20px;color:var(--accent)}.post--regulation h1{justify-content:center}.post--regulation h2{justify-content:center;margin-bottom:10px}.post--regulation h2+h2{margin-top:-10px;margin-bottom:20px}.post-list .post-date{color:var(--accent-alpha-70);text-decoration:none}.post-list a{text-decoration:none}.post-list .post-list-title{text-decoration:underline}.post-list .post-tag{text-decoration:underline}.pagination{margin-top:50px}.pagination__title{display:flex;text-align:center;position:relative;margin:100px 0 20px}.pagination__title-h{text-align:center;margin:0 auto;padding:5px 10px;background:var(--background);font-size:.8rem;text-transform:uppercase;letter-spacing:.1em;z-index:1}.pagination__title hr{position:absolute;left:0;right:0;width:100%;margin-top:15px;z-index:0}.pagination__buttons{display:flex;align-items:center;justify-content:center}@media (max-width: 683px){.pagination__buttons{flex-direction:column}}.button{position:relative;display:inline-flex;align-items:center;justify-content:center;font-size:1rem;border-radius:8px;max-width:40%;padding:0;cursor:pointer;appearance:none}@media (max-width: 683px){.button{max-width:80%}}.button+.button{margin-left:10px}.button a{display:flex;padding:8px 16px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.button__text{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.footer{padding:40px 0;flex-grow:0;opacity:.5}.footer__inner{display:flex;align-items:center;justify-content:space-between;margin:0;width:760px;max-width:100%}@media (max-width: 899px){.footer__inner{flex-direction:column}}.footer a{color:inherit}.footer .copyright{display:flex;flex-direction:row;align-items:center;font-size:1rem;color:var(--light-color-secondary)}.footer .copyright--user{margin:auto;text-align:center}.footer .copyright>*:first-child:not(:only-child){margin-right:10px}@media (max-width: 899px){.footer .copyright>*:first-child:not(:only-child){border:none;padding:0;margin:0}}@media (max-width: 899px){.footer .copyright{flex-direction:column;margin-top:10px}}@media (max-width: 899px){.footer .copyright-theme-sep{display:none}}@media (max-width: 899px){.footer .copyright-theme{font-size:.75rem}} \ No newline at end of file diff --git a/public/tags/index.html b/public/tags/index.html new file mode 100644 index 0000000..390fe46 --- /dev/null +++ b/public/tags/index.html @@ -0,0 +1,170 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + + + + +
    + +
    + +
    + + + diff --git a/public/tags/linux/index.html b/public/tags/linux/index.html new file mode 100644 index 0000000..335f838 --- /dev/null +++ b/public/tags/linux/index.html @@ -0,0 +1,212 @@ + + + + + +Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/tags/luan-qi-ba-zao/index.html b/public/tags/luan-qi-ba-zao/index.html new file mode 100644 index 0000000..d7f6dfc --- /dev/null +++ b/public/tags/luan-qi-ba-zao/index.html @@ -0,0 +1,448 @@ + + + + + +Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    +

    + tag: #乱七八糟 + (30 posts) +

    + + + Show all tags + + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/tags/tan-tian-shuo-di/index.html b/public/tags/tan-tian-shuo-di/index.html new file mode 100644 index 0000000..3cf1f8f --- /dev/null +++ b/public/tags/tan-tian-shuo-di/index.html @@ -0,0 +1,162 @@ + + + + + +Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + + + + +
    + +
    + +
    + + + diff --git a/public/tags/wang-luo-yi-shu/index.html b/public/tags/wang-luo-yi-shu/index.html new file mode 100644 index 0000000..1e50fc3 --- /dev/null +++ b/public/tags/wang-luo-yi-shu/index.html @@ -0,0 +1,232 @@ + + + + + +Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/tags/windows/index.html b/public/tags/windows/index.html new file mode 100644 index 0000000..521d8cc --- /dev/null +++ b/public/tags/windows/index.html @@ -0,0 +1,208 @@ + + + + + +Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + + + + +
    + +
    + +
    + + + diff --git a/public/tags/zong-he-gong-cheng/index.html b/public/tags/zong-he-gong-cheng/index.html new file mode 100644 index 0000000..cc0e851 --- /dev/null +++ b/public/tags/zong-he-gong-cheng/index.html @@ -0,0 +1,202 @@ + + + + + +Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + + + + +
    + +
    + +
    + + + diff --git a/public/variables.css b/public/variables.css new file mode 100644 index 0000000..e69de29 diff --git a/public/weekly/index.html b/public/weekly/index.html new file mode 100644 index 0000000..12b6768 --- /dev/null +++ b/public/weekly/index.html @@ -0,0 +1,745 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    +
    + +

    谈天说地:狄奇周刊(二一)

    + + + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(二十)

    + + + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(十九)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(十八)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(十七)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(十六)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(十五)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(十四)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(十三)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(十二)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(十一)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(十)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(九)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(八)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(七)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,每周四更新.PS:因为昨天输入法突发恶疾,所以无法按时更新。

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(六)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,每周四更新.

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(五)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,每周四更新.

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(四)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,每周四更新.

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(三)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,这周三提前一天更新.

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(二)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,暂定每周四进行更新.

    +
    + + + +
    + +
    + +

    谈天说地:狄奇周刊(一)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,暂定每周四进行更新.

    +
    + + + +
    + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-1/index.html b/public/weekly/zhoubao-1/index.html new file mode 100644 index 0000000..19926b7 --- /dev/null +++ b/public/weekly/zhoubao-1/index.html @@ -0,0 +1,234 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(一)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,暂定每周四进行更新.

    +

    事记

    +

    一.Google直接将广告嵌入视频避免被屏蔽

    +

    据广告拦截软件 SponsorBlock 开发者发布的消息,YouTube 正在测试直接将广告从服务端注入到视频中

    +

    这种技术对服务端的基础设施要求应该是非常高的,因为 YouTube 仍然需要考虑个性化广告,即每次需要将针对特定用户感兴趣的广告注入到视频流的特定位置。当然用户观看界面也需要做一些改变,因为进入广告片段后还需要提供能够给用户点击链接的交互选项,避免广告确实被用户看了,但感兴趣的用户没法直接点击广告内容。

    +

    那么有办法能够继续屏蔽这种视频流广告吗?应该是有的,SponsorBlock 认为既然 YouTube 需要在前端界面提供可点击的链接,那就必然需要加载某段代码用来标记广告频段出现的时刻,如果能检测到视频流中的广告时刻,那么进行针对化的操作也可以跳过广告,最简单的方式就直接快进这部分。

    +

    二.国内Docker镜像站全部下架

    +

    SJTUG(上海交通大学 Linux 用户组)6月6日发布公告:

    +
    +

    非常遗憾,接上级通知,即时起我们将中止对 dockerhub 仓库的镜像。docker 相关工具默认会自动处理失效镜像的回退,如果对官方源有访问困难问题,建议尝试使用其他仍在服务的镜像源。我们对给您带来的不便表示歉意,感谢您的理解与支持。

    +
    +

    原公告"接上级通知","因监管要求"等字眼,现在已经被删除。随后,中科大及多家其他镜像站也接连停止服务。 +据称,是有人上传了关于涉政人物的AI语音合成器的docker镜像。

    +

    随后发现原来去年就有了一个 "AtomHub 可信镜像中心",由开放原子开源基金会主导,华为、浪潮、DaoCloud 、谐云、青云、飓风引擎以及 OpenSDV 开源联盟、openEuler 社区、OpenCloudOS 社区等成员单位共同建设。

    +

    V2EX上的讨论:如何评价新一代的国产可信 Docker 镜像中心 Atomhub

    +

    三.Windows11更新推送安装微软电脑管家

    +

    如果你的windows没有关闭自动更新,那么会被捆绑安装微软电脑管家。该软件提供多种语言,不过现阶段只在中国市场进行推送安装。理论上只要是系统区域设置为中国的设备接下来都会自动安装微软电脑管家,不需要经过用户的任何点击。

    +

    目前可以在设置中卸载微软电脑管家,但继续安装后续的更新就不知道微软是否还会继续给用户捆绑安装。

    +

    据反馈不少人对其持中立态度,因为该软件空间占用非常小且功能实用,不过笔者一向对这些管家类软件抱警惕态度

    +

    四.Google Chrome 开始淘汰 Manifest V2 扩展

    +

    从 2024 年 6 月 3 日起在 Chrome Dev、Canary 和 Beta 渠道,如果用户仍然安装有 Manifest V2 扩展,那么用户访问扩展管理页面 chrome://extensions 时会显示警告信息,通知他们 Manifest V2 扩展将很快不予支持。。短时间内禁用的 Manifest V2 扩展可以重新启用,但未来将会被彻底禁用

    +

    Manifest V3 受争议之处是它限制了 WebRequest API 的功能,用 declarativeNetRequest 替代了 WebRequest。广告屏蔽扩展如 uBlock Origin 会受到影响,因为它们使用 WebRequest 在广告下载前屏蔽其请求。禁用 Manifest V2 扩展意味着 uBlock Origin 会被禁用。

    +

    开发者已经释出了使用 Manifest V3 的精简版本 uBO Lite,其功能弱于原版。原版未来只能在 Firefox 等浏览器上使用。

    +
    +

    PS:利好Firefox系浏览器

    +
    +

    五.国产NAS绿联系统帮助文件惊现群晖内容

    +

    最近NAS赛道又被卷的火热,由于行业龙头群晖价格偏高,这几年国产 NAS 也是百花齐放,联想、架那极空间、海康威视、绿联等等纷纷入场。

    +

    5月23号绿联也是发布了自己最新的NAS系列产品,宣发力度非常大,吸引了很多用户购买。但用户使用的过程中发现了很多问题,比如 CPU 温度过高,相册备份失败,甚至 App 账号注册登陆流程都没法顺利进行等等。

    +

    最让人绷不住的是使用手册上竟然直接出现了友商“群晖”的字样。

    +

    6月3日晚上绿联被喷的把新 NAS 京东天猫全部下架,并发布了致歉信。

    +

    结合这个时间点,可以合理推测可能是领导层为了赶 618 活动,导致开发不得不硬着头带 BUG 上线。

    +

    六.小米澎湃OS限制安装未知应用权限次数

    +

    小米的米柚自 MIUI 9+ (Based on Android 7+ \ SDK 27+) 在安装未知应用(侧载安装未在应用商店商家认证的应用)时,引入了安装应用未知来源需要 SIM 卡的限制;安装未知应用权限,每张SIM卡拥有一定次数的限制,超限后无法申请该权限。

    +
    +

    微博网友:那我要是不插卡呢?给不了权限!

    +
    +

    其实这个安全性限制原生 Android 也有,当然类原生 Android 也有,只不过需要 SIM 卡限制是小米自己魔改加上去的。

    +
    # adb shell
    +adb shell settings put secure install_non_market_apps 1
    +adb shell appops set <package_name> REQUEST_INSTALL_PACKAGES allow
    +
    +

    或者安装Termux,并获取相应root权限后,使用 Termux 终端,在 shell 交互窗口设置也行:

    +
    pkg install root-repo
    +tsu
    +
    +settings put secure install_non_market_apps 1
    +appops set <package_name> REQUEST_INSTALL_PACKAGES allow
    +
    +

    记得把<package_name>替换成相应的包名,比如 com.topjohnwu.magisk + 

    +

    七.讯飞输入法服务器崩溃竟然无法离线使用

    +

    多名网友反馈,讯飞输入法出现异常,从晚上7点多开始无法正常弹出键盘,点击提示则显示无法加载资源等

    +

    要不是此次崩溃可能大家还没意识到讯飞输入法是完全依赖云端服务器的,即无法在离线的情况下使用,这个确实有些匪夷所思。

    +

    故障持续已经有两个小时,讯飞输入法官方没有发布回应,也没有完成修复;

    +

    讯飞输入法官方微博在用户评论中回复:

    +
    +

    您好,非常抱歉给您使用带来困扰~ 讯飞输入法在配置端午节运营活动过程中出现bug,导致部分用户出现客户端崩溃问题。输入法团队正在对此进行全力抢修,6月5日晚会发布新版本修复问题,新版本发布后、升级版本可恢复使用。 再次表示抱歉,感谢理解与支持~

    +
    +

    另外根据网友反馈此次讯飞输入法崩溃只影响官方版,诸如小米定制版的讯飞输入法是正常的,这也可以看出来定制版使用的可能不是讯飞的服务器,所以并没有发生崩溃

    +
    +

    所谓的"大数据"大头就在与输入法上传数据并推送个性化广告

    +
    +

    文推

    +

    咖啡简史

    +

    数字记忆指南

    +

    拟物图标的消失

    +

    何加盐|中文互联网正在加速崩塌

    +

    Windows 设计史 01 | 从青涩到成熟(Windows 1.0 - 95)

    +

    Windows 设计史 02 |「海王星」项目,「稳定」表象背后的求索

    +

    Windows 设计史 03 | Windows XP:摆脱机械,拥抱自然

    +

    项目

    +

    996忍者摸鱼站

    +

    Ploopy耳机:一套开源3D打印耳机

    +

    一个极简的RSS在线浏览工具

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-10/index.html b/public/weekly/zhoubao-10/index.html new file mode 100644 index 0000000..49d43f5 --- /dev/null +++ b/public/weekly/zhoubao-10/index.html @@ -0,0 +1,188 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(十)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +

    事记

    +

    一.研究员:Windows 系统防火墙无法阻止 IPv6 远程代码执行漏洞

    +

    根据赛博昆仑实验室研究员Wei透露的部分消息,攻击者构造的IPv6数据包在到达防火墙进行数据处理之前就可能被触发,因此仅通过开启系统的IPv6防火墙并不能有效阻止攻击。

    +

    结合该漏洞的特性,这进一步验证了之前的推测,即该漏洞可以用于在内网中进行横向攻击,特别是通过内网IPv6地址实施攻击。由于部分场景下的内网设备长期无法进行系统更新,该漏洞对这些没有网络隔离且长期无法更新系统的环境构成了更大的威胁。

    +

    二.婚姻登记条例拟修订,结婚和离婚不再需要户口簿

    +

    8月13日,民政部发布了新的《婚姻登记条例》修订草案,面向社会公开征求意见。草案对结婚和离婚程序进行了调整,取消了户口簿的要求,登记地点也不再受限。

    +

    此外,新增了30天离婚冷静期的具体规定,“离婚冷静期“期间任何一方可申请撤回,并明确了隐瞒重大疾病可导致婚姻被撤销。草案还要求婚姻登记必须免费,确保个人隐私保密,并规定婚姻登记机关要提供婚姻辅导服务。(这部分细则看全文)

    +

    三.韩国监管机构:KakaoPay向支付宝擅自提供用户信息

    +

    韩国金融监督院8月13日表示,韩国移动支付服务商 KakaoPay 近六年来未经用户同意向中国支付平台支付宝擅自提供了 4000 万名用户的 542 亿条个人信用信息。据悉,为了满足与苹果公司合作的先决条件,支付宝要求 KakaoPay 提供全体用户的信用信息。而 KakaoPay 未经用户同意就提供了支付宝所要求的全部信息,其中甚至包括未使用过跨境支付服务的用户信息。根据双方合作内容,KakaoPay 用户可在与支付宝签署支付服务协议的线上线下商店进行支付。

    +

    四.华为HarmonyOS NEXT对Webview加入了风险网站检查API

    +

    ArkTS API 11+ 可以启用检查网站安全风险的功能。开发文档显示违规和诈骗网站的检查是默认启用的,不能通过此接口关闭;风险网站的检查是默认关闭的,可以通过此接口开启或关闭。

    +

    违规和诈骗网站的检查会发送 URL 哈希前缀和网站域名到服务器做检测,风险网站的检查会发送 URL 哈希前缀和脱敏 URL(删除 URL 的查询参数)到服务器做检测。

    +

    文推

    +

    text软考高级架构师备考记录

    +

    2024年上半年无线路由器选购攻略

    +

    Exploring TLS certificates and their limits

    +
    +

    项目

    +

    基于 LaTeX 的简历生成器

    +

    记录 5 个世纪技术与社会发展的巨型图谱

    +

    免费的开源跨平台游戏引擎

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-11/index.html b/public/weekly/zhoubao-11/index.html new file mode 100644 index 0000000..cf0e2dd --- /dev/null +++ b/public/weekly/zhoubao-11/index.html @@ -0,0 +1,216 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(十一)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +

    事记

    +

    一.开源软件 Aria 被诈骗份子利用导致作者被跨省

    +

    Aria 是一个高性能、轻量级、易于使用的文件下载框架,主要应用于 Android 平台,目前在 GitHub 上有超过 5600 个 Star。

    +

    Aria 开发者写道:“因 Aria 被诈骗分子使用,导致我被跨省,因此本项目源码永久删除。”

    +

    二.巴基斯坦政府称使用VPN是导致该国网速变慢的原因,反对者怀疑政府正在建墙

    +

    数周以来,巴基斯坦的互联网速度一直非常缓慢,但谁应该为此负责,这仍是一个有争议的问题。

    +

    活动人士称,国家正在建设中国式的互联网防火墙,以进一步控制网络空间。官员们对这些说法提出质疑,并将爬行速度降低的原因归咎于安全连接或 VPN 的广泛使用。关闭互联网来压制异议是巴基斯坦和亚洲其他地区监管机构的常见做法。

    +

    自去年前总理伊姆兰汗引发骚乱以来,政府封锁了社交媒体平台,限制了网速,争取公众支持的斗争从街头蔓延到了数字空间。信息技术国务部长沙扎·法蒂玛周日表示,政府并不是近期网络放缓的原因。法蒂玛女士表示,“大量人口”一直在使用 VPN,“这给网络带来了压力,导致互联网速度变慢”。

    +
    +

    VPN应用在巴西应用商店下架

    +
    +

    包括NordVPN、ExpressVPN和Surfshark在内的数十款VPN应用已经从巴西的苹果应用商店下架。根据Top10VPN的研究主管Simone Magliano的报告,至少有30款VPN应用消失了。著名的免费VPN提供商Proton VPN确认了这一问题,并猜测可能是“系统故障,或苹果在执行某种隐秘的审查命令。”

    +

    此事件发生之际,X(前称Twitter)刚刚宣布关闭其巴西业务,原因是该公司未遵守巴西最高法院法官亚历山德雷·德·莫赖斯的审查要求,否则其法律代表将面临逮捕的“秘密命令”。

    +

    三.AMD发布Adrenalin 24.8.1驱动,优化《黑神话:悟空》等游戏并新增Radeon Anti-Lag 2技术支持

    +

    AMD推出了最新的Adrenalin 24.8.1 WHQL驱动程序,为《黑神话:悟空》、《星鸣特攻》、《星球大战:亡命之徒》以及《使命召唤:黑色行动6》公测版等游戏提供支持。新版驱动还为《对马岛之魂导剪版》引入了Radeon Anti-Lag 2技术,该技术能够在开启FSR3帧生成功能时,在4K极高画质设置下降低RX 7800 XT显卡的延迟高达28%。同时,新版驱动扩展了HYPR-Tune支持范围,为《使命召唤:现代战争III》、《漫威蜘蛛侠:重制版》和《漫威蜘蛛侠:迈尔斯・莫拉莱斯》新增FSR 3自动配置,并宣布HYPR-Tune支持HYPR-RX以启用AMD FidelityFX等游戏内技术。

    +

    四.中国联通拒收电信CN2的国际路由

    +

    据 DMIT 援引中国电信集团北京公司的消息,中国联通现已确认拒绝接收任何来自中国电信CN2的国际路由。

    +

    据了解,该变化影响中国联通用户接入CN2网络的能力,原先通过CN2 GIA的去程发生改变,回程目前未受影响。中国电信计划通过海外与中国联通进行互联以解决此问题。

    +

    DMIT 称,已注意到 AS4809(CN2)、AS23764(CGT) 与 AS10099(联通国际) 之间的对等网络出现拥塞,将接入香港、东京和洛杉矶的中国联通线路,以提高中国联通客户的网络质量。该运营商还重申了对 Pro 和 EB 系列产品网络质量的保证。

    +

    五.iOS新Bug曝光:四个字符可致iPhone崩溃

    +

    网络安全研究员Konstantin 发现,一个新的字符漏洞可导致 iPhone 和 iPad 崩溃。在滑动到 App 库后,在搜索框中输入 "":: 四个字符,将导致Springboard 重置,iPhone 会返回到锁屏界面。重置并非完全重启,iPhone 只需几秒钟即可恢复正常。

    +

    测试发现,只需要输入 "": 和任何其他字符即可触发崩溃;重置问题似乎仅出现在运行 iOS 17 的设备上,iOS 18 设备上如此操作不会导致重置,但会出现一些奇怪的问题,例如字符消失和设置应用崩溃。

    +

    文推

    +

    论佼佼者

    +

    哪些事你去了北欧才知道

    +

    “吃饱饭才多久?”

    +

    【CDT百科】“历史的垃圾时间”是什么梗

    +

    如何在没有屏幕的情况下安装家用 Linux 服务器?

    +

    【读书记1487-1】周濂《正义的可能》:我们应该如何生活

    +

    A Starter’s guide on recovering damaged and rotten CDs

    +
    +

    项目

    +

    快捷键大全

    +

    readme 文档如何写

    +

    博搜·Telegram导航

    +

    自托管的食谱管理器和膳食计划器

    +

    3613 个公司高清 Logo 的收集网站

    +

    一个提供性姿势的详细信息和指导的网站

    +

    一个免费、开源、功能强大的登陆页面模板

    +

    免费和开源的机器翻译 API,自托管,支持离线

    +

    在shell中将sing-box/mihomo作为客户端运行

    +

    一个基于「 太微 TiddlyWiki 」的知识管理桌面应用

    +

    一个开源的“即将推出”和 SaaS 平台和网站的等待列表页面

    +

    Go语言写就的一个轻量级、自托管友好的 RSS 聚合器和阅读器

    +

    基于自定义规则的番剧采集APP,支持流媒体在线观看,支持弹幕。

    +

    一站式开源高质量数据提取工具,支持PDF/网页/多格式电子书提取

    +

    一个开源的跨平台文件浏览器,由用 Rust 编写的虚拟分布式文件系统提供支持

    +

    Huly — 多合一项目管理平台(替代 Linear、Jira、Slack、Notion、Motion)

    +

    bytebase 为开发人员、DBA 和平台工程团队提供世界上最先进的数据库 DevOps 和 CI/CD

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-12/index.html b/public/weekly/zhoubao-12/index.html new file mode 100644 index 0000000..4da46bb --- /dev/null +++ b/public/weekly/zhoubao-12/index.html @@ -0,0 +1,219 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(十二)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +

    事记

    +

    一.猴痘病毒被发现可以通过呼吸道飞沫传播

    +

    据新华社报道,泰国公共卫生部召开新闻发布会,称该国发现了首例猴痘Ib变异株病例。此次发现的该种变异株新增了可通过呼吸道飞沫等分泌物、皮疹、受感染物品等的传播途径。此外,包括中国在内的多个国家已开启针对入境人员的防疫措施。

    +

    二.微软“闯祸”Linux躺枪:更新之后,Linux打不开了

    +

    两年前GRUB有个漏洞,能绕过安全启动机制;微软去修 Windows+Linux 的双OS用户的 GRUB 引导,修坏了... +此次事件中受到波及的,是Windows+Linux的双系统用户

    +

    安装更新后,这些用户在启动Linux时会发生报错,提示“出现严重错误”。

    +
    Verifying shim SBAT data failed: Security Policy Violation.
    +shim SBAT数据校验失败:违反安全策略
    +Something has gone seriously wrong: SBAT self-check failed: Security Policy Violation.
    +出现严重错误:SBAT自检失败:违反安全策略
    +
    +

    应急补救措施——

    +

    首先进入BIOS关闭安全启动,目的是先进入到Linux系统。

    +

    之后利用命令行把引发故障的SBAT策略删除,然后重启让设置生效。

    +

    最后,再次进入BIOS重新打开安全启动,问题就暂时解决了。

    +

    三.微软正式确认:Windows 控制面板将被弃用

    +

    微软一直致力于为 Windows 添加新功能,同时也会淘汰一些不再必要的旧功能。这些功能会被添加到 Windows 过时功能列表中,最近的一个是 Paint 3D,微软宣布其即将被淘汰。与 Paint 3D 类似,微软似乎也希望尽快淘汰控制面板。

    +

    早在 2011 年,就有传闻称微软计划用“PC 设置”取代控制面板。虽然“PC 设置”的设计更加适合触摸操作,但控制面板仍然存在。

    +

    直到几天前,微软才在其网页上正式发布相关信息。在一个关于各种原生 Windows 配置工具的新支持页面上,微软终于表示,控制面板“正在被弃用,取而代之的是设置应用”。

    +
    +

    控制面板是于 1985 年首次在 Windows 1.0 中引入的。

    +
    +

    四.Telegram 创始人帕维尔-杜罗夫在巴黎被捕

    +

    据法国媒体TF1 Info报道,加密通讯公司 Telegram 的创始人兼首席执行官帕维尔·杜罗夫 (Pavel Durov) 于法国时间24日晚上 8 点(北京时间周日凌晨 2 时)左右在勒布尔热机场的停机坪上从私人飞机上下来时被捕。这位 39 岁的法俄混血男子由他的保镖和一名女子陪同。

    +

    根据通缉人员档案,杜罗夫从阿塞拜疆直接抵达。Telegram 创始人头上挂着法国司法警察局 OFMIN(隶属于法国海关部门的国家反欺诈办公室)签发的法国搜查令,该搜查令在初步调查的基础上签发。

    +

    法国当局认为,Telegram 缺乏审核、与执法部门的合作以及其提供的工具(一次性号码和加密货币)使其成为贩毒、恋童癖和欺诈的帮凶。但该搜查令只有当帕维尔·杜罗夫在法国国土上时才有效。

    +

    当前,ONAF 的调查人员通知了他并将其拘留。他应该在本周六晚上被送交调查法官,然后周日可能会因多项罪行被起诉:恐怖主义、毒品、同谋、欺诈、洗钱、收受赃物、儿童犯罪内容等。

    +
    +

    Toncoin 价格 已下跌17.4%,部分交易所出现 20% 以上的剧烈跌幅

    +
    +

    五.无线充电新规9月1日起施行:MagSafe/Qi2因频率冲突停售,iPhone无线功率调整至7.5W

    +

    中国将于2024年9月1日起实施新的《无线充电(电力传输)设备无线电管理暂行规定》,规定无线充电设备的工作频率和额定传输功率。MagSafe和Qi2协议使用的频率为360kHz,不符合新规要求的频率范围,可能面临停售。工信部明确指出,325-405KHz频段在中国不可用于无线充电设备。苹果官网已更新iPhone的无线充电参数,显示额定传输功率为7.5W,工作频率为127.7kHz,符合新规。

    +

    苹果iPhone 15等机型目前仍显示支持MagSafe与Qi2无线充电,最高功率达15W。新规施行后,不符合要求的设备将停止生产或进口,但已生产或进口的设备可继续销售至报废。新规对无线充电设备市场及苹果产品销售策略可能产生影响。

    +

    文推

    +

    靠打零工生活的年轻人挤在廉价青旅

    +

    月薪10万的人,不想吃鼎泰丰了

    +

    短篇漫画小狐狸化形记

    +

    普通人该如何认清当下的经济环境

    +

    计算机学院的老师们的实际编程能力如何

    +

    终于可以愉快地扫描了:Linux 扫描仪配置与使用攻略

    +

    《一人企业方法论》第二版,也适合做其他副业(比如自媒体、电商、数字商品)的非技术人群

    +
    +

    项目

    +

    网站图标下载器

    +

    开源的豆瓣替代品

    +

    微信公众号文章批量下载工具

    +

    Megalodon 的一个分支,功能丰富

    +

    Zen Browser:基于firefox的新浏览器

    +

    Supersonic:自托管音乐服务器的轻量全功能跨平台桌面客户端

    +

    Go 语言开发的个人阅读/观影/看剧/追番/游戏记录 Web 管理工具

    +

    Deku SMS – 开源安卓短信工具,支持 Webhook、SMTP、FTP 转发短信|集成 RabbitMQ

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-13/index.html b/public/weekly/zhoubao-13/index.html new file mode 100644 index 0000000..0582e3c --- /dev/null +++ b/public/weekly/zhoubao-13/index.html @@ -0,0 +1,201 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(十三)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +

    事记

    +

    一.广东也来啦:数码家电以旧换新立打 8 折补贴 2000 元,合计 16000 元

    +

    广州家电以旧换新补贴(京东平台)现已开始发放,包含冰箱、洗衣机、电视、空调、电脑、热水器、吸油烟机、家用灶具

    +

    虽然名为“广州以旧换新”,但目前广东省内都可领取。

    +

    与北京补贴不同的是,本次下单地址限广东省内

    +

    每人 8 个品类每种都可参与一次,单次至高补贴 2000 元,合计至高可减 16000 元。

    +

    本次活动于 2024 年 9 月 1 日开启,预计结束时间为 2024 年 12 月 31 日

    +

    二.Linux Kernel 6.12 版预计将支持在崩溃后显示二维码 后续可以解码排查错误

    +

    7 月份时红帽工程师基于 systemd 255 + 版的全屏显示错误消息功能为 Linux Kernel 开发崩溃后显示二维码选项,这与微软在 Windows 10/11 蓝屏死机后显示二维码有异曲同工之妙。

    +

    不过 Linux 与 Windows 在崩溃时显示的二维码内容则有本质区别,因为 Windows BSOD 显示的二维码实际就是微软帮助文档的链接,属于固定内容二维码。

    +

    Linux Kernel 的崩溃后显示二维码是将崩溃日志生成二维码,这样崩溃日志不会被截断,用户在必要的时候对二维码进行拍照以后后续解码内容分析崩溃的具体原因。

    +

    经过两个月的讨论后目前红帽工程师准备的代码已经通过 DRM-Misc-Next 提交给 DRM-Next,以便能够赶上 Linux Kernel 6.12 的合并窗口,如无意外的话 Linux Kernel 6.12 将是首个支持崩溃后显示二维码的内核版本。

    +

    值得注意的是显示二维码功能是红帽工程师使用 Rust 语言编写的,因此必须启用 Rust 内核构建后才能使用此功能,在构建中可以通过 DRM_PANIC_SCREEN_QR_CODE Kconfig 作为功能开关配置。

    +

    三.国铁新规:列车有权拒绝“买短乘长”旅客继续乘车

    +

    9月1日,2024版《中国国家铁路集团有限公司铁路旅客运输规程》(简称《国铁集团客规》)在铁路12306网站全文发布。特别的,第三十五条明确,旅客要求越过车票到站继续乘车时,须在原车票到站前提出,在有运输能力的情况下列车可予以办理,核收越站区间的票款;无运输能力时,列车有权拒绝旅客补票和继续乘车

    +

    有铁路工作人员此前介绍,平时铁路运能充裕,可以为旅客办理“买短乘长”补票。但买短乘长又往往集中出现在运能紧张的客流高峰时期,这时,工作人员会根据客流情况,决定是否办理越站补票手续。如果列车旅客过多影响到运行,就不会办理补票,“买短乘长”的旅客可能会被劝导下车。

    +

    四.我国将建立统一电子烟交易管理平台,价格仍由市场决定

    +

    烟草局计划建立一个统一的电子烟交易管理平台。该平台将执行统一标准,确保电子烟合法销售。电子烟、雾化物和烟碱生产企业、电子烟批发和零售商等各类电子烟市场主体应当通过平台进行交易。

    +

    同时坚持市场决定价格,建立完善主要由市场调节的电子烟产品价格形成机制。

    +

    此外,进口电子烟同一规格实行全国统一销售价格,并在平台上公开。

    +

    五.谷歌已向 AOSP 推送安卓 15 源代码

    +

    今天,谷歌正式向安卓开源项目 (AOSP) 推送安卓 15 的源代码。安卓 15 将在未来几周内在受支持的 Pixel 设备上推出,并将在未来几个月内在三星、荣耀、iQOO、联想、摩托罗拉、Nothing、OnePlus、Oppo、realme、夏普、索尼、Tecno、vivo 和小米的精选设备上推出。谷歌在博客文章中表示,我们很自豪能够通过 AOSP 继续开展开源工作。开源允许任何人以安卓为基础进行开发和贡献,从而打造出更加多样化和创新的设备。

    +

    六.互联互通:淘宝平台拟全面引入微信支付

    +

    从多位知情人士处获悉,淘宝平台拟全面引入微信支付,成为阿里系平台与腾讯之间互通的标志性事件。据了解,淘宝打通微信支付在淘天集团内部属于保密项目,该项目的筹备始于半年前,由用户端基础工具团队在主要对接。今年6月,手淘已有部分用户灰测使用微信支付,不过仅支持购买部分商品时可选择。据了解,淘宝接入微信支付这个项目,淘天是更加积极推动的一方,此举从业务到战略层面,对阿里都有重大意义。

    +

    文推

    +

    Inside.git

    +

    用软件定义无线电(SDR)做的 50 件事

    +

    Rust 嵌入式开发(ESP32 处理器)系列文章

    +
    +

    项目

    +

    Bangumi for Android - 适用于 bangumi.tv 的功能齐全的非官方 android 原生应用程序

    +

    使用 Shizuku 的出色 Android 应用程序精选列表

    +

    使用ThinkPHP开发的开源发卡站模板

    +

    学习音乐

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-14/index.html b/public/weekly/zhoubao-14/index.html new file mode 100644 index 0000000..6ec7fc2 --- /dev/null +++ b/public/weekly/zhoubao-14/index.html @@ -0,0 +1,216 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(十四)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +

    事记

    +

    一.阿里云新加坡节点崩了,客服回应:新加坡机房出现火灾

    +

    9月10日,有消息称阿里云新加坡节点出现网络崩溃情况。

    +

    相关工作人员表示,阿里云新加坡地域可用区C网络访问出现异常,阿里云的工程师正在紧急处理中。该工作人员还补充道,出现异常是由于新加坡机房出现火灾。

    +

    据了解,阿里云成立于2009年,是一家云计算和人工智能科技公司。

    +

    今年7月份,阿里云也曾出现网络异常问题。彼时,阿里云发布消息称,阿里云监控发现上海地域可用区N网络访问出现异常,经阿里云工程师紧急介入处理后,于当日10:35完成网络切流调度后,10:42访问异常问题恢复。

    +

    目前云服务ECS、对象存储、云数据库等仍然未恢复,中断时间已超48小时。

    +

    此次事件导致如PikPak、Lazada(东南亚最大电子商务平台)、字节海外服务均受影响,PikPak目前服务仍不稳定。

    +

    二.微软 Azure 云服务和 Microsoft 365 发生重大服务中断

    +

    微软公司称用户可能无法从 AT&T 公司网络访问其 Azure 云服务,并正在调查可能发生的中断事件。微软还确认 Microsoft 365 服务目前已停止服务,该问题影响了 Teams、Outlook 以及更多服务。

    +

    据 Downdetector 数据,截至美国东部时间上午 8:58,已报告约 21,000 起 Microsoft 365 中断事件。

    +

    三.OpenAI发布o1系列模型:AI推理能力迈向新高度

    +

    2024年9月12日,人工智能领域的领军企业OpenAI宣布推出全新的o1系列模型,标志着AI推理能力的重大突破。这一系列模型专门设计用于解决复杂问题,在科学、编程和数学等领域展现出前所未有的性能。

    +
      +
    • 深度推理机制
    • +
    +

    o1系列的核心创新在于其独特的"深度思考"机制。通过先进的训练方法,模型能够在生成回答前进行更全面、深入的推理过程。这种方法使AI能够:

    +

    尝试多种解决策略 +识别并纠正推理过程中的错误 +逐步优化思考路径

    +
      +
    • 性能评估
    • +
    +

    在严格的性能测试中,o1系列模型展现出卓越表现:

    +

    国际数学奥林匹克竞赛(IMO)资格考试:o1模型正确率达83%,远超GPT-4o的13% +Codeforces编程竞赛:达到89百分位水平 +物理、化学、生物学等领域:表现接近博士生水平

    +
      +
    • 安全性提升
    • +
    +

    OpenAI为o1系列开发了创新的安全训练方法,充分利用模型的推理能力来加强安全性:

    +

    "越狱"测试:o1-preview模型得分84分(满分100分),大幅领先于GPT-4o的22分 +新的安全训练方法使模型能够更好地理解和应用安全准则

    +
      +
    • o1-mini:轻量级推理模型
    • +
    +

    为满足不同应用需求,OpenAI同时推出o1-mini模型:

    +

    运行速度更快,成本降低80% +保留强大的推理和编程能力 +适用于需要高效推理但不需要广泛世界知识的场景

    +

    文推

    +

    推荐系统如何让我们变得极端 - 中国数字时代

    +

    为什么每个 User-Agent 都有 Mozilla 字样?

    +
    +

    项目

    +

    日语五十音字帖 - GitHub

    +

    Rust 写的可滚动平铺窗口管理器

    +

    FerrumC 是一个Rust 编写的 Minecraft 服务器实现

    +

    一个自托管的书签应用程序(链接、笔记和图像),具有基于 AI 的自动标记和全文搜索功能

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-15/index.html b/public/weekly/zhoubao-15/index.html new file mode 100644 index 0000000..da108b7 --- /dev/null +++ b/public/weekly/zhoubao-15/index.html @@ -0,0 +1,194 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(十五)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +

    事记

    +

    一. 微软考虑彻底封闭Windows内核

    +

    微软在今年7月的蓝屏危机后曾讨论过完全封闭 Windows 的内核。近期微软再次发布一篇文章称,「公司正致力于为内核模式之外的解决方案提供商提供更多安全功能」。

    +

    现在许多游戏都使用了内核级别的反作弊程序,但是许多开发商关闭了Linux兼容层,导致 Linux 无法通过 Proton 或是Wine来运行这些 Windows 游戏。随着主流系统更新,内核级的反作弊、客户端的反作弊或将逐渐淘汰,服务器端反作弊方案将成为新选择。不论是从游戏性能还是安全角度,或是设备系统兼容,这对于玩家来说都是一件好事。

    +

    二.Intel大转型:年底前裁掉15000人、剥离代工、德国厂暂停、减少2/3房产

    +

    当地时间9月16日,Intel首席执行官帕特·基辛格 (Pat Gelsinger) 在最新的股东大会之后,发布了一封公开信,对于近期相关传闻进行了回应,并全面概述了Intel的转型计划。

    +

    在8月初公布了糟糕的财报及财测数据,并宣布全球裁员15%、削减资本支出(到2025年削减100亿美元资本支出)、暂停每季派息之后,Intel受到了来自投资者、政府、内部员工、社会舆论等诸多方面的巨大压力。

    +

    由此,也引发了诸如“Intel将出售晶圆制造业务”、“Intel将出售FPGA(Altera)业务”、“高通将收购Intel部分芯片设计业务”、“Intel将暂停海外晶圆厂建设”等一系列的传闻。

    +

    三.Mozilla :将于 12 月 17 日关闭 Mozilla.social 实例

    +

    2024年9月18日——Mozilla 宣布将于2024年12月17日停止其社交平台 Mozilla.social 的实验,届时 Mastodon 实例将正式关闭。用户仍可在12月17日前继续使用 Mozilla.social,并在此日期之前下载相关数据或将账户迁移至其他 Mastodon 实例。

    +

    12月17日之后,Mozilla.social 的 Mastodon 实例将彻底关闭,平台上的所有内容和账户将无法再访问。不过,用户的 Mozilla 账户仍将继续有效,可以用于访问 Mozilla 的其他产品和服务。用户可以通过 Mozilla 官网管理其账户信息。

    +

    四.华为正式弃用 Windows,余承东:华为 PC 将全部用鸿蒙

    +

    在近期的 Mate XT 交付仪式上,华为消费者业务 CEO 余承东说,华为的个人电脑产品将全面弃用 Windows 系统,转而采用自家研发的鸿蒙操作系统。主要受到美国制裁的影响,华为加速了技术自主化的进程。

    +

    余承东表示,华为已经能够完全替代美国的技术和元件,未来的新一代笔记本将提供与 Mac 类似的操作体验,旨在打造统一的生态系统,提升用户体验。鸿蒙系统的成功将直接影响华为在全球市场的竞争力。

    +

    五.AWS 将 OpenSearch 移交给 Linux 基金会

    +

    近日在奥地利举办的开源峰会(Open Source Summit)上,亚马逊宣布将其旗下OpenSearch开源项目捐赠给 Linux 基金会,该基金会已经成立 OpenSearch 软件基金会,用来支持该项目及其搜索和分析软件的研发。

    +

    OpenSearch 是 Elasticsearch 和 Kibana 的开源分支,现在已正式成为 Linux 基金会开源项目家族的一部分。Linux 基金会表示,OpenSearch 被世界各地的软件开发人员用来构建搜索、分析、可观察性和矢量数据库应用程序,下载量业已超过 7 亿次。OpenSearch 软件基金会将与社区维护者和开发人员以及创始成员组织合作,支持 OpenSearch 的持续发展。

    +

    文推

    +

    如何无痛早起

    +

    一个平庸的人,活着的意义是什么?

    +

    磨合

    +
    +

    项目

    +

    一个收集了几乎所有苹果产品参数的网站

    +

    Buttplug-一款开源的成人玩具控制工具

    +

    一个轻量级的AI证件照制作算法,支持自托管

    +

    GlazeWM 是受 i3wm 启发的 Windows 平铺窗口管理器

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-16/index.html b/public/weekly/zhoubao-16/index.html new file mode 100644 index 0000000..7a21c5b --- /dev/null +++ b/public/weekly/zhoubao-16/index.html @@ -0,0 +1,196 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(十六)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +

    事记

    +

    一.CloudFlare WARP 支持 MASQUE 协议

    +

    近日,CloudFlare WARP 客户端更新后带来了 MASQUE 协议支持,用户可以在客户端设置菜单中进行切换。MASQUE 是基于 HTTP/3 和 QUIC 的新协议,能高效代理 IP 和 UDP 流量,同时保持性能和隐私。该协议还将使 WARP 的流量看起来像 HTTPS,以避免被防火墙检测和阻止,并符合 FIPS 标准的加密。

    +

    二.12306新增车内换座功能

    +

    客服表示,车内换座功能是近期刚上线的,具体来看,车内换座属于中转票的一种,是分段售卖,之前需要消费者一段一段去查,现在是12306系统可以优先算出这一趟车的线路并做出提示,用户可以分段购买同一趟车次的车票,到了中转站在车上直接换座即可。“其实就相当于买了两段行程,只不过两段行程是在同一辆车上,不需要换乘。”客服表示。

    +

    上述客服称,价格方面,会比直达的车票贵一些,“因为是分段售卖,每段加起来的价格一般会比直接买全程价格高。”

    +

    12306平台另一客服也表示,车内换座是为没抢到直达车票的用户提供的功能,即使有优惠的话分段票价加起来也比直达的要贵。

    +

    中新经纬查询发现,并非每趟列车都有车内换座功能,且车内换座的价格确实比直达票价要贵一些。

    +

    以9月30日北京南到上海虹桥站,6点10分发车的G101次高铁为例,二等座直达票价为626元,如果选择中转,在南京南进行车内换座,二等座的价格为504元(北京南到南京南)+153元(南京南到上海虹桥)共657元,两者差31元;一等座价格分别为1035元(直达)和1086元(车内换座),两者相差51元;商务座价格为2318元(直达)和2432元(车内换乘),相差114元。

    +

    三.OpenSSH 9.9 发布

    +

    OpenSSH 9.9 新增并默认启用了对 mlkem768x25519-sha256 混合量子抗性密钥交换算法的支持。该算法巧妙地结合了 FIPS 203 模块格密钥封装机制 (ML-KEM) 和 X25519 椭圆曲线 Diffie-Hellman (ECDH),大幅提升了系统抵御量子计算威胁的能力。

    +

    四.国家广电总局研发出能同时控制电视和机顶盒的遥控器

    +

    在国务院新闻办公室今天举行的“推动高质量发展”系列主题新闻发布会上,国家广播电视总局透露已研发出能够同时控制电视机和机顶盒的新型三模通用遥控器,广电总局广播电视科学研究院也已经研制了 8 款只有 U 盘大小、可以隐藏在电视机后面的微型机顶盒。

    +

    目前中央和省级电视台已经全部实现了高清化播出,地市台频道高清化率已经超过 98%,全国已经开办了 9 个超高清频道。有线电视网络和 5G 协同发展,广电 5G 用户已经超过了 2800 万。网络视听持续繁荣,用户规模已经达到 10.68 亿。

    +
    +

    中国广电总局:有线电视和IPTV全面取消开机广告

    +
    +

    文推

    +

    居家健身入门指南

    +

    为什么古埃及后来不再建造金字塔了?

    +

    云手机底层技术揭密 : Android系统启动与Magisk原理

    +
    +

    项目

    +

    一个漂亮的面板

    +

    Vim Cheat Sheet

    +

    UI 用于在 Linux 上使用 eBPF 嗅探网络流量

    +

    massCode 是一个为开发人员设计的开源代码片段管理器

    +

    Slash 是一个开源的自托管平台,旨在帮助您组织、管理和共享最重要的链接

    +

    风传 WindSend 用于在不同设备之间快速安全的传递剪切板,传输文件或文件夹

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-17/index.html b/public/weekly/zhoubao-17/index.html new file mode 100644 index 0000000..a5f4646 --- /dev/null +++ b/public/weekly/zhoubao-17/index.html @@ -0,0 +1,209 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(十七)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +

    事记

    +

    一.小米澎湃 OS 国际版也开始限制解锁BL,不少国外网友抱怨无法解锁

    +

    早前小米已经对澎湃 OS 国内版施加解锁限制,要想申请解锁 Bootloader 必须参与答题以及积极参与小米社区并在社区等级达到 5。

    +

    现在小米澎湃 OS 国际版也开始限制,倒不是非得参与什么社区,而是用户申请时总是提示名额已经用尽需要等待几天再申请。

    +

    在小米澎湃 OS 海外社区申请解锁的贴子中大量国外网友在抱怨小米施加的限制,显然这不可能是突然大量用户申请解锁导致名额用尽,而是小米故意施加的限制但没有公开披露。

    +

    有网友抱怨自己尝试了几个月都没有拿到解锁名额解锁自己的小米手机,抱怨小米给消费者制造麻烦,当然更大的问题是没有透明度,小米既没有公开披露为什么要限制也没有披露什么时候才能恢复正常。

    +

    对消费者来说目前最大的问题就是不能解锁那也无法刷机,部分玩家爱好者希望解锁 Bootloader 就是希望能够刷机或者对 ROM 进行微调,例如可以使用 Magisk+ROOT 权限获得更多功能。

    +

    小米暂时还未对此事进行回应,所以还不清楚小米为什么要施加限制,但考虑到现在已经不是刷机时代,小米应该也不至于担心是刷机造成自己的广告费流失吧。

    +

    二.外卖骑手抢单外挂“死神”等被捣毁 涉案3000万元、112人被抓

    +

    9月28日消息,公安部网安局发文称,浙江省绍兴市新昌公安破获一起非法抢单外挂软件案,涉案金额达3000余万元。

    +

    该作案团伙上下游分工明确,结构清晰,从软件开发到渠道销售、运维等,全链路均涉及,并由不同人员负责。

    +

    这个外挂软件名叫“死神”,并先后迭代12个版本,演化为“雷神”“波点”等多个软件,在全国范围内均有兜售。

    +

    非法销售外挂软件的人员宣称,外卖骑手花几十块钱买一个激活码后,即可非正常抢单。此类外挂软件通过非法读取各类App的订单框架,设置抢单条件,实现自动化、定制化抢单功能。

    +

    在美团安全团队的支持配合下,新昌公安经过对线索的全面收集和深入研判,已抓获违法犯罪嫌疑人112名(其中,刑事打击14人,行政处罚2人),批评教育71人。

    +

    目前,该案中为首的犯罪嫌疑人被依法判处有期徒刑三年半,案件仍在进一步侦查办理中。

    +

    三.日本兵库县一名50多岁的男性警司强迫21名部下下载Temu帮忙“砍一刀”被处以警告

    +

    根据兵库县警察公开的信息显示,兵库县警察局对本部安全科的一名 50 多岁男性警司持续要求 21 名下属在在线购物应用 Temu 并注册的行为进行了警告。该应用允许那些推荐朋友的人获得特殊福利,当事人说:“我就是想要一份礼物。”据县警方称,3月至6月期间,该男警司通过LINE等渠道向其手下的21名男警官发送信息,称“免费注册”、“请帮我们获得5份免费礼物”等内容。他敦促他们注册成为 Temu 的会员。一些下属在与另一位上级协商后发现了这一事件。在县警察进行的一项调查中,21 人中有 12 人表示他们对该应用感到“不舒服”,15 人在注册后立即删除了该应用。

    +

    四.规模之大刷新世界纪录,Cloudflare 成功抵御 3.8Tbps 的 DDoS 攻击

    +

    10 月 2 日消息,Cloudflare 今日发文称,其 DDoS 保护系统自 9 月初以来一直在抵御一个超大规模的 L3/4 DDoS 攻击。

    +

    此次攻击一直持续了一整个月,期间包括一百多次超大规模攻击,其中最大一次攻击达到 3.8Tbps,是已公开过的最大规模的一次攻击。

    +

    Cloudflare 表示,这些攻击主要利用固定端口上的 UDP,且源自全球各地,占比较大的数据来于越南、俄罗斯、巴西、西班牙和美国。

    +

    此次攻击活动针对的是金融服务、互联网和电信等行业的多个客户。此次攻击活动的目标是带宽饱和以及在线应用程序和设备的资源耗尽。高数据包速率攻击似乎源自多种类型的受感染设备,包括 MikroTik 设备、DVR 和 Web 服务器,这些设备协同工作,向目标发送大量流量。高比特率攻击似乎源自大量受感染的华硕家用路由器,可能是利用了 Censys 最近发现的 CVE 9.8(严重)漏洞。

    +

    五.FAT32支持到2TB了 但exFAT格式才是你的首选

    +

    8月16日,微软推送了Windows 11 Build 27686预览版更新,除了全新的Windows Sandbox Client预览版外,在格式化命令从命令行格式化磁盘时,FAT32的大小限制也从32GB提高到了2TB,这意味着现在即使是2TB的U盘或移动硬盘,也可以使用FAT32格式。

    +

    FAT32是1995年随Windows 95 OSR2一同发布的文件系统,它继承了FAT16的优点,并解决了后者单个分区大小不超过2GB的问题。理论上FAT32支持的存储容量可以达到16TB,但Windows系统之前将其限制在32GB,这主要是其原理上的缺陷。

    +

    一方面,FAT32几乎都用在U盘、存储卡等移动存储设备(硬盘从WindowsNT后开始逐步普及NTFS),而早期这些移动存储设备容量普遍偏小,如果默认的簇偏大就会造成磁盘空间的浪费,即使小到几个字节的超微型程序,也会占用完整的32KB存储空间,所以微软才做出如此的限制。

    +

    除此之外,FAT32在原理方面的缺陷,还容易产生严重的文件碎片,从而影响读写速度,这也是Windows95/98操作系统内置磁盘碎片清理的原因。不过,FAT32无法处理超过4GB的单个文件,这对于高清视频、大型数据库或虚拟机镜像等应用场景来说是致命的。

    +

    虽然NTFS克服了上述的问题,同时还拥有极高的安全性,但基本仅限于Windows系统使用,其他的操作系统例如macOS、Linux等无法直接读写,而数码相机、智能手机和平板电脑也不支持,因此FAT32依然是移动设备最常用的文件系统。

    +

    为了解决FAT32存在的问题并适应日益增长的数据存储需求,微软于2006年推出了exFAT(Extended File Allocation Table),但直到近些年才被发扬光大,例如一部1080P的蓝光电影普遍超过10GB,这时候除了NTFS,可用的磁盘格式也只能是exFAT了。

    +

    exFAT保持了与多种操作系统的良好兼容性,尤其是在日常生活中,移动硬盘、U盘和存储卡等经常会遇到需要跨越不同平台进行数据交换的情况,而exFAT凭借其出色的跨平台兼容性和高效稳定的特性,成为了许多用户的首选,几乎所有的操作系统和设备都能完美支持。

    +

    更重要的是,exFAT可以支持的最大卷尺寸几乎是无限的,即使是多TB级别的硬盘也能被有效利用,而且不受限于4GB的天花板,用户可以轻松地传输任何大小的媒体文件或其他类型的大文件。同时,更先进的算法极大减少了磁盘碎片产生的可能性,提升了整体效率。

    +

    FAT32曾经是许多人记忆中不可或缺的一部分,但毕竟廉颇老矣,即使分区限制提升到了2TB也无法有效满足需求,一方面是单个多媒体文件早已超过4GB,另一方面移动固态硬盘的容量也已经达到了8TB,因此exFAT格式才是跨系统、跨平台移动存储的唯一选择。

    +

    文推

    +

    Linux 下的字体调校指南

    +

    Make - 独立创造者小书 读书笔记

    +

    一文讲清CPE、MiFi和物联卡:是「流量自由」还是「坑蒙拐骗」?

    +
    +

    项目

    +

    《动手学深度学习》

    +

    UniGetUI:包管理器的图形界面。可以被糟糕地描述为管理包管理器的包管理器

    +

    功能齐全的本地 AWS 云堆栈。离线开发和测试您的云和无服务器应用程序

    +

    合并 UT 词典将多个 Mozc UT 词典合并为一个

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-18/index.html b/public/weekly/zhoubao-18/index.html new file mode 100644 index 0000000..e89c5bb --- /dev/null +++ b/public/weekly/zhoubao-18/index.html @@ -0,0 +1,197 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(十八)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +

    事记

    +

    一.英国移交查戈斯群岛主权至毛里求斯,ccTLD .io 或将被废弃。

    +
      +
    • io 是 ISO 分配给英属印度洋领地 (British Indian Ocean Territory, BIOT) 的国家编码; .io 亦被分配为此地区的 ccTLD。
    • +
    • 由于 IO 在计算机概念中的重要性 (Input/Output),.io 域名被大量科技类企业及站点所使用。
    • +
    • 在 .su (前苏联) 和 .yu (南斯拉夫) 的废弃乱象后,IANA 出台了更严格的 ccTLD 废弃流程,而这套流程即将适用于 .io。
    • +
    +

    二.Windows 11 24H2 问题导致8.63GB的更新缓存无法清理

    +

    除了光标消失问题,Windows 11 24H2 更新还会导致创建一个无法使用磁盘清理删除的 8.63GB 更新缓存。虽然 Windows 更新缓存非常正常并且在磁盘清理或存储清理等工具中可见,但 Windows 11 24H2 中的一个奇怪错误阻止了用户清除更新缓存或文件。磁盘清理和存储设置尝试删除更新缓存文件,但不起作用,缓存一直占用高达 8.63 GB 的存储空间。Windows 11 修复安装也无法解决此问题,但全新安装确实可以解决问题。微软公司表示,已经注意到用户的反馈,并计划在即将发布的更新中发布修复程序。

    +

    三.Android 将推出官方 Linux 终端应用

    +

    Google 正在为 Android 开发一个官方的 Linux 终端应用。这个应用将允许用户在 Android 设备上运行 Linux 命令,类似于 Chromebook 上的 Crostini。

    +

    开发人员可以通过开发人员选项启用终端应用程序,并将在虚拟机中安装 Debian。

    +

    四. 海康威视进行大规模人员优化,或影响上千员工

    +

    海康威视正在实施大规模的组织调整,32个研发区域将收缩至12个,预计裁员规模将超过1000人,研发部门受影响最为严重。部分被裁员工透露,裁员会有“N+2”的赔偿方案,部分地区如湖南已经完成裁员,杭州总部尚未开始。

    +

    近年来,公司营收和净利润增速下滑,2024年第二季度净利润同比下降10.7%,低于市场预期,增收不增利的局面尤为突出。软件业务收入占比下降,进一步加剧了公司的增长压力。

    +

    文推

    +

    各种限流算法的可视化对比

    +

    各种负载均衡策略的可视化对比

    +

    输出我做独立开发和对互联网的一些思考

    +

    内存是怎么映射到物理地址空间的?内存是连续分布的吗?

    +
    +

    项目

    +

    自己动手写 Git

    +

    好看的终端工具

    +

    各品牌手机root情况汇总

    +

    在终端里面看天气

    +

    Lem 是专为 Common Lisp 调整的编辑器/IDE

    +

    一个漂亮的windows皮肤

    +

    在Minecraft 里跑一个linux | Linux in Minecraft

    +

    一款适用于班级多媒体屏幕的课表的信息显示工具,可以一目了然地显示各种信息

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-19/index.html b/public/weekly/zhoubao-19/index.html new file mode 100644 index 0000000..a56f2bc --- /dev/null +++ b/public/weekly/zhoubao-19/index.html @@ -0,0 +1,196 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(十九)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +

    事记

    +

    一.Win 11 24H2 更新导致部分西数SSD用户蓝屏

    +

    Windows 11 24H2 更新导致某些 PC 崩溃并出现蓝屏死机 (关键进程已死亡)。微软已经意识到了这一点,并计划暂停今年在受影响硬件上的更新。据透露,微软已经意识到少数搭载西部数据特定 SSD 的设备可能会遇到蓝屏死机错误的问题。蓝屏死机与存储驱动程序和 RAID 控制器有关。WD SN770 会提供 200MB 主机内存缓冲区 (HMB),而 23H2 只会分配 64MB 所以没有问题,然而 24H2 会分配完整的 200MB ,并导致蓝屏死机错误“关键进程已死亡”。用户虽然可以通过设置注册表“HMBAllocationPolicy = 0”关闭 HMB 来缓解该问题,但可能会影响硬盘性能。

    +

    二.Ubuntu诞生20周年:Canonical发布了即将到来的24.10版本——它一如既往的出色

    +

    The story of Ubuntu is a story written by many hands. This page is a tribute to our community, partners and Canonical staff who have all given a piece of themselves to making this open source project thrive. Thank you to all of you. +Ubuntu的故事是由许多人书写的故事。 此页面是向我们的社区、合作伙伴和 Canonical 员工致敬,他们为使这个开源项目蓬勃发展做出了自己的贡献。 谢谢大家。

    +

    Above all, it’s a celebration of what Ubuntu has achieved so far, and an invitation to collaborate with us in delivering an even faster pace of innovation in the future. +最重要的是,这是对 Ubuntu 迄今为止所取得的成就的庆祝,并邀请我们与我们合作,在未来提供更快的创新步伐。

    +

    三.Linux 内核将数名与俄罗斯联邦相关的贡献者从维护者列表中移除

    +

    日前,Linux 内核主要维护者之一 Greg Kroah-Hartman (Greg K-H) 提交了一项不寻常的“文档”更新,将数名具有 <.ru> 顶级域名邮箱的维护者,和一名明确为俄罗斯身份的维护者从 MAINTAINERS(维护者名录)文件除名。

    +

    这一提交已于上周日被 Linus Torvalds 拉取并包含于 6.12-rc4 版本的代码中。

    +

    Greg K-H 并未详述这项更新的具体原因,仅含糊其辞地表示该更改是“由于某些合规性要求”,并指出“(相关人员)提供充足文档后,方可回归(维护者名录)”。

    +

    相关的维护者移除方式相当暴力,其中部分子系统由于唯一维护者使用 <.ru> 顶级域名邮箱,整个子系统都被从 MAINTAINERS 文件中移除,这之中不乏诸如 UFS 文件系统和 PPTP 驱动等重要且被广泛使用的子系统。由于 Linux 内核开发流程完全基于邮件列表进行,当 MAINTAINERS 文件中移除相关维护者后,也就意味着与相关子系统的补丁或沟通将不再被发送至维护者的邮箱,乃至相关的邮件列表。这很可能会造成许多补丁“石沉大海”;而如果某个子系统未得到充分维护,那么其被从内核中移除也只是时间问题了。

    +

    通常而言,Linux 内核补丁除了发送至邮件列表外,还需要抄送与之相关的人士(如子系统维护者和活跃贡献者),并且经过讨论和审阅后才会被拉取合并。然而,Greg K-H 似乎刻意绕过了这部分流程,仅仅将补丁发送至流量最大、几乎不会有人认真阅读每封邮件的 patches@lists.linux.dev 列表,并于仅仅两天后就向 Linus Torvalds 发起拉取请求,而 Torvalds 亦未对相关修改提出质疑和意见便拉取合并这笔更改了。

    +

    考虑到 Linus Torvalds 与 Greg K-H 均受雇于 The Linux Foundation,后者为注册在美国的 501(c)(6) 组织,“某些合规性要求”为何显而易见。

    +

    截至发稿时,Greg K-H 尚未回应邮件列表上的相关质询。无论结果为何,这都将是 Linux 内核社区历史上最为耻辱的提交之一。

    +

    四.RackNerd 和 CloudCone 服务出现中断

    +

    RackNerd 服务状态显示,其位于洛杉矶DC-02 所在的大楼出现火警,洛杉矶消防局因此切断了供电,DC-02的所有服务器受到影响。RackNerd 强调该公司服务器所在楼层没有火灾,因此数据是安全的。

    +

    据了解,RackNerd DC-02由跨国宽带网络服务提供商 MultaCom 直接运营。另外一家运营商 CloudCone 也在此处托管有大量服务器。今天CC同样出现了大面积服务中断,截止目前该公司尚未发布通告。

    +

    文推

    +

    图解网络协议系列

    +

    MySQL的性能优化

    +
    +

    项目

    +

    出色的网络安全手册

    +

    egos-2000 :仅用 2000 行代码就实现了教育操作系统的每个组件

    +

    海狸笔记

    +

    开源免费采集 HTTP(S) 流量软件 ProxyPin,支持全平台系统

    +

    适用于 Windows 10/11 的通用窗口升频器

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-2/index.html b/public/weekly/zhoubao-2/index.html new file mode 100644 index 0000000..98e226d --- /dev/null +++ b/public/weekly/zhoubao-2/index.html @@ -0,0 +1,203 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(二)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,暂定每周四进行更新.

    +

    事记

    +

    一.宁德时代施行 896 工作制,向员工发出“奋斗 100 天”号召

    +

    近日一份文件显示,宁德时代向员工发出了“奋斗100天”的号召。即符合条件的员工从6月12日起,施行896的工作日,即早上8点上班,晚上9点下班,每周工作6天,共“奋斗”100天。

    +

    另外,还有补充通知说明:外籍员工不强制,按照他们的意愿。据了解,此次已不是第一次宁德时代号召“奋斗100天”,早在2022年的一篇报道中,宁德时代就被提到:奋斗100天已成常态化。

    +
    +

    宁德时代内部员工回应“896工作制”

    +
    +

    今日有消息称,宁德时代向员工发出了“奋斗100天”的号召,即符合条件的员工从6月12日起,施行“896”的工作日,即早上8点上班,晚上9点下班,每周工作6天,共“奋斗100天”。有宁德时代内部员工对财联社记者表示确有此事,上周五部门开会口头通知此事,并表示:“之前是也要加班,但不强制到九点。”另有知情者透露,该号召是针对一定级别以上员工,并非所有员工。截至发稿前,宁德时代官方尚未对财联社记者给予回复。

    +

    二.国产游戏《黑神话:悟空》再次登顶

    +

    6月18日,Steam平台最新一周销量榜出炉(6月11日-6月18日),国产游戏《黑神话:悟空》再次登顶,达成全球二连冠。而在前一日晚间,《黑神话:悟空》在京东开启第二轮PC实体版预售几乎秒售罄,与第一轮情况相同。

    +

    根据官方信息,《黑神话:悟空》PC实体豪华版售价820元,限量20000套;收藏版售价1998元,限量10000套。目前豪华版预约人数已超过20万人,收藏版预约人数已超过41万人。

    +

    这款游戏的开发商游戏科学成立于2014年,由原腾讯《斗战神》网游项目核心成员冯骥和杨奇等人创立,其中冯骥是《斗战神》项目的主策划。

    +

    三.618手机战绩出炉:苹果靠降价登顶,小米紧随其后

    +

    在采取更加大力度的降价策略后,苹果继续把持京东相关排行榜的第一位。截至19日6点18分,在京东618手机竞速榜上,苹果拿下了手机品牌销量与销售额的双料第一。单品方面,其iPhone 15 Pro Max、iPhone 15 Pro以及iPhone 15,分别拿下第一、第二和第四。

    +

    过去半年来,苹果已多次以官方名义降价促销,在竞争激烈的中国市场“贴身肉搏”。事实证明,这一策略收效甚好。苹果之外,小米再次拿下国产品牌阵营第一,其在京东、天猫、拼多多、抖音、快手等平台上均为国产手机销量及销额的双第一。小米在今年618中出现了明显增幅。截至18日24时,小米618大促全渠道累计支付金额达到263亿元,创出其历年大促的新纪录。

    +

    四.安卓15新功能:自动删除效果不佳的生物识别模型

    +

    最新的 Android 15 测试版中操作系统框架中的字符串显示,系统会自动检测面部或指纹模型何时效果不佳,并删除它们,然后提示用户重新设置。将显示一条通知,提示您的面部或指纹模型“运行不正常,已被删除。请重新设置以使用您的脸部或指纹解锁手机”。由于安卓只允许注册一个面部模型,因此重新注册面部时显示的通知与重新注册指纹时显示的通知略有不同,但功能上没有区别。目前尚不清楚系统是如何判断生物识别数据效果不佳的,甚至不确定是否在最新的 Android 15 测试版中上线。

    +

    五.法国法院下令谷歌、Cloudflare 和思科的公共DNS屏蔽指定的盗版网站

    +

    法国巴黎法院在5月份应版权方要求,命令谷歌、CloudFlare 和思科在其公共 DNS 系统里屏蔽约117个盗版网站域名。此次屏蔽的网站主要涉及的版权内容是英超联赛和欧冠联赛,提交申请的版权方则是 Canal+,该版权方还要求法国当地 ISP 即网络运营商也通过 DNS 系统屏蔽这些域名。通过相关公开数据谷歌代表律师认为这大约影响了800多名法国用户,所以实际影响可以说微乎其微或者说完全没有。

    +

    六.上海地铁一男子持刀和人发生肢体冲突后续:已被警方刑事拘留

    +

    19日,上海市公安局城市轨道和公交总队官方微博发出通报称,早上8时28分,轨交9号线合川路站内发生一起持刀伤人案。54岁犯罪嫌疑人沈某(男)行凶后,导致3人受伤。沈某被抓。

    +

    网传视频显示,地铁内多处有血迹,其中一名男子倒地,多名工作人员互相呼叫、前来包扎施救。现场有的民众快速离开,有的在远处围观。

    +

    网民猜测:“54岁中年失业男?上次吉林市北山公园那个也是55岁中年失业男。”网民所说“吉林市北山公园”事件市指,6月10日,美国爱荷华州康奈尔学院(Cornell College)4名教师在吉林省吉林市北山公园被刺伤。行凶者为55岁吉林市龙潭区男子崔某某。

    +

    文推

    +

    113 自行车系列2 组成自行车的五大系统

    +

    真实的硅谷是怎么样的?

    +

    一个离谱但有效的锻炼方法,比运动轻松多了!

    +

    那些原本是废话的常识|小学生吐槽食堂之后:看,社会又来教“做人”了

    +

    项目

    +

    飞鱼 : 一个漂亮的跨平台视频播放器,支持docker部署。

    +

    Nullboard : 是看板/任务列表管理器的极简风格,设计紧凑、可读且易于使用。单页 Web 应用程序 - 只有一个 HTML 文件、一个古老的 jQuery 包和一个 webfont 包,可以完全离线使用。

    +

    OnionPlay : 一个免费提供最新电影和电视剧在线播放的网站,无广告干扰。

    +

    Z-Library图书馆 : 可以使用的官方域名大全。

    +

    开源大模型食用指南 : 基于Linux环境快速部署开源大模型。

    +

    中小学人教版教材下载 : 内容全面,速度快

    +

    小初高电子教材免费下载页(WEB在线下载) : 无需登陆,下载稍慢,次数有限

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-20/index.html b/public/weekly/zhoubao-20/index.html new file mode 100644 index 0000000..989b601 --- /dev/null +++ b/public/weekly/zhoubao-20/index.html @@ -0,0 +1,193 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(二十)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +

    事记

    +

    一.哔哩哔哩大会员限制只能同时2个终端使用

    +

    近日,哔哩哔哩对大会员服务协议内容进行了更新和优化,更新版本主要针对使用限制的情形相对应的条款进行调整:(一) 同一账号同一时间最多可以在2个终端设备使用会员服务,终端设备包括但不限于手机端、电脑端、平板电脑端、网页端等 (包括小程序) 以及上述终端相应的网页端;(二) 同一账号在手机端24小时内至多支持在2个设备上使用会员服务;(三) 超过上述范围使用的,哔哩哔哩大会员将会根据情况中止或终止对您提供的服务,且哔哩哔哩大会员保留采取进一步措施的权利,包括但不限于追偿损失等。

    +

    二.7-Zip再曝高危漏洞

    +

    近日,7-Zip被曝出编号为CVE-2025-0411的高危漏洞,该漏洞允许远程攻击者绕过Windows的“网络标记”(Mark-of-the-Web, MOTW)保护机制,从而在受影响的系统上执行任意代码。此漏洞影响24.07及之前的所有7-Zip版本,建议用户尽快升级至24.09版本以修复漏洞,确保系统安全。

    +

    三.NVIDIA CUDA将「冻结」三大老架构

    +

    NVIDIA CUDA将「冻结」三大老架构

    +

    NVIDIA在最新的CUDA 12.8开发包更细日志中明确表示,针对Maxwell、Pascal、Volta三大老架构的支持,已经完成了所有功能特性,未来的新版本中将处于「冻结」状态。CUDA开发包仍会继续支持它们,但不会有任何新功能。

    +

    四.微软E5开发者订阅已经全球下架

    +

    据用户反映并通过微软客服专员证实,微软已在全球范围内下架E5开发者订阅。

    +

    此消息意味着,长期以来被许多用户视为免费网盘福利的E5订阅及其附带的大容量云存储空间,即将成为历史。

    +

    文推

    +

    自洽的程序员

    +

    系统设计面试:内幕指南

    +

    停服、倒闭,一家被大厂抄袭的小公司之殇

    +

    项目

    +

    Quant Wiki 中文量化百科

    +

    哔哩哔哩账号备份

    +

    用 nextUI 写的阅读体验更好的 Miniflux 第三方 Web 前端

    +

    Serial Studio能够与串行端口、网络套接字和 MQTT 代理进行交互

    +

    Ghostty 是一款快速、功能丰富且跨平台的终端仿真器,它使用平台原生 UI 和 GPU 加速。

    +

    一款无服务端的多协议云盘文件上传和管理应用,支持多种存储协议,包括本地文件、FTP、SFTP、S3、SMB、Webdav等

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-21/index.html b/public/weekly/zhoubao-21/index.html new file mode 100644 index 0000000..cbc433d --- /dev/null +++ b/public/weekly/zhoubao-21/index.html @@ -0,0 +1,192 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(二一)

    + + + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +

    事记

    +

    一.Cloudflare推出验证在线图片的真实性的功能

    +

    Cloudflare采用由Adobe主导的“内容凭证”系统,为图片和视频添加数字元数据标签,追踪其所有权、发布历史以及是否经过篡改,特别是是否使用了生成性AI工具。

    +

    Cloudflare还推出了一个“保留内容凭证”的一键设置功能,适用于所有通过Cloudflare Images托管的内容,用户可以通过Adobe的“内容真实性”网页工具或Chrome扩展程序,轻松验证这些图片的数字历史。

    +

    该系统基于“内容来源与真实性联盟”(C2PA)制定的开放标准,旨在帮助艺术家和摄影师保留作品的归属权,并帮助用户区分真实和经过AI工具生成或篡改的图像与视频。

    +

    二.Apple开源 Xcode 底层构建引擎 Swift Build

    +

    苹果正式宣布将 Swift Build 开源,并纳入 Swift 项目,致力于为所有 Swift 用户提供更强大且统一的跨平台构建体验。Swift Build 作为 Xcode 的底层构建引擎,已为数百万 App 和苹果自家操作系统构建流程提供支持,现开源后也可面向 Linux、Windows 等平台。

    +

    Swift Package Manager 将逐步采用统一引擎,确保在所有平台和工具中获得一致的构建体验,并为后续新功能和性能改进铺平道路。目前,Swift Build 已在 GitHub 的 Swift 组织下公开,社区开发者可提交反馈与改进建议,共同推进这一新里程碑的发展。

    +

    三.Firefox 离线翻译插件在 Nightly 上已经开始支持中译英。

    +

    此插件是 Project Bergamot 的一部分,后者由欧盟资助,旨在提升浏览器离线机器翻译的效果。

    +

    插件目前支持 12 种语言,包括德语、西语、俄语、葡萄牙语、意大利语等。

    +

    四.小米向 AOSP 提交补丁,拟禁止用户通过 adb 等方式提取 APK 文件

    +

    一位小米工程师向 AOSP 提交了一个补丁,该补丁将添加一个 SELinux 策略,禁止用户通过 adb 等方式来提取 APK 文件,理由是 APK 中可能会包含一些「私有资源」。

    +

    该补丁提交后,在 AOSP Code Review 中引起热议。该工程师称,“APK 只应该从谷歌市场或其他应用市场等可靠来源获取,如果一个 APK 可以被 adb 提取,它就可以被反编译,这样会有一定的安全风险。”。有网友在下面顺势质问小米不开源内核,小米并未对此答复。

    +

    好在 Google 拒绝将此补丁合入 AOSP,并称“APK 基本上不是(原文大写强调)秘密”,但 Google 拒绝合并并不意味着 MIUI 不会采取措施来进一步限制用户权限,好时代,来临力🤮

    +

    五.DeepSeek发布的开源推理大模型R1震动全球AI圈

    +

    1 月 20 日,DeepSeek 发布了全新的开源推理大模型 DeepSeek-R1,在数学、编程和推理等多个任务上达到了与 OpenAI o1 相当的表现水平,同时将API调用成本降低了 90-95%。

    +

    和上次不同的是,这次推出的新模型DeepSeek-R1不仅成本低,更是在技术上有了大福提升。

    +

    AI圈大V Yuchen Jin认为,DeepSeek-R1 论文中的这个“顿悟时刻”意义巨大:纯强化学习 (RL) 使LLM自动学习思考和反思。

    +

    这挑战了之前的观点,即复制 OpenAI 的 o1 推理模型需要大量 CoT 数据。事实证明,你只需要给予它正确的激励即可。

    +

    文推

    +

    让 Android 手机更省电流畅,你可以试试「刷内核」

    +

    《纽约客》主编专访比尔·盖茨|盖茨和新晋特朗普科技寡头

    +

    对 DeepSeek 真实水平的分析

    +

    项目

    +

    互传联盟,在不同品牌设备上互传

    +

    SamWaf开源轻量级网站防火墙,完全私有化部署

    +

    在PDF里运行Linux,利用RISC-V模拟器,将Linux系统嵌入PDF文件,基于TinyEMU,支持32位和64位系统;

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-3/index.html b/public/weekly/zhoubao-3/index.html new file mode 100644 index 0000000..2c9e0c8 --- /dev/null +++ b/public/weekly/zhoubao-3/index.html @@ -0,0 +1,212 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(三)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,这周三提前一天更新.

    +

    事记

    +

    一.阿桑奇刑满出狱

    +

    朱利安·阿桑奇(Julian Assange)在同意对违反美国《间谍法》的一项指控认罪后已经出狱。预计本周在北马里亚纳群岛的美国法庭出庭后,他将获得自由。26日,阿桑奇承认了一项“共谋获取和披露国防信息”的刑事指控。法官判处阿桑奇在狱中服刑期满,他已重获自由并将返回澳大利亚。)

    +

    二.湖北电信屏蔽苹果ESS查询服务导致iMssage登录和互联互通无法使用

    +

    近期,湖北电信的部分宽带用户遭遇了苹果设备功能异常,包括iMessage、FaceTime、Apple TV屏幕镜像、HomePod使用受限及连续互通功能失效。起初,人们怀疑是苹果设备的问题,但随着网上讨论增多,发现受影响的用户主要集中在特定的宽带运营商服务范围内。经分析,宽带服务商屏蔽了identity.apple.com域名,导致设备无法正常验证Apple ID状态,进而影响功能使用。

    +

    使用在线路由追踪验证了湖北电信和联通的线路,发现联通线路能正常与苹果服务器通信,而电信则在本地终止。

    +
    +

    解决方法

    +
    +

    三.CSDN的gitcode正在批量搬运github

    +

    近期,有网友在csdn推出的gitcode中发现了自己在github上的项目,而自己并未入驻gitcode。

    +

    经测试发现,github 上的仓库几乎都搬了过去,不过也根据关键词屏蔽了一些仓库。

    +

    比较有趣的是,可能csdn没有设置vpn相关的屏蔽词,因此上面有许多的vpn教程仓库,甚至有许多敏感话题的仓库.

    +

    大家可以试试搜搜,看看自己的github有没有被搬运。

    +
    +

    随后由于热度较高,目前GitCode无法正常访问,ITdog测速全红;然后又被V友爆料对敏感仓库进行的是前端屏蔽,可谓抽象.

    +
    +

    四.Linux 资深网络开发者 Larry Finger 去世

    +
    +

    2024-06-24 17:37 by RIP

    +
    +

    Linux 资深网络开发者 Larry Finger 于 6 月 21 日去世,享年 84 岁。他的妻子在 linux-wireless 邮件列表上通过了一份简短声明发布了他去世的消息。Larry Finger 自 2005 年起参与 Linux 内核无线驱动的开发,近二十年来向主线内核贡献了逾 1500 个补丁。最初是博通的 BCM43XX 驱动,近期则是 RTW88、RTW89、R8188EU、R8712、RTLWIFI、B43 等内核网络驱动。部分是由于他的贡献,Linux 无线硬件支持过去二十年取得了长足进步

    +

    五.中国公司帮助缅甸屏蔽 VPN

    +

    缅甸军政府从 5 月 30 日起开始屏蔽 VPN 使用,如赛风和NordVPN等。军政府还让士兵随机检查行人的手机,寻找是否安装了非法 VPN 应用。报道称,有城市居民因为安装了 VPN 应用被罚款 300 万缅元(1380 美元),如果付不起钱则会遭到逮捕。知情人士称,军政府雇佣了一家中国公司实现 VPN 屏蔽,屏蔽使用了来自中国的软件。Access Now 的亚太政策分析师 Wai Phyo Myint 表示,军政府过去三年一直在寻找最新技术和工具加强对信息访问的控制,最新禁令是至今最严厉的互联网访问限制。

    +

    六.京东禁止用户使用第三方比价工具或插件,否则将限制账号使用

    +

    从6月22日开始多名网友收到京东商城发来的通知短信,在短信中京东称监测到用户账号可能被恶意使用,如果用户使用第三方比价工具或插件则必须卸载并修改京东账号密码否则账号将被持续进行限制

    +

    目前电商网站类的比价工具、扩展程序乃至使用脚本进行嵌入式比价的非常多,京东此番操作将会影响不少用户,逼迫用户停止使用此类软件。

    +
    +

    另附:中国“618”购物节销售额首次下降

    +
    +

    随着中国电商平台竞相提供全年大幅折扣,中国的网络购物节正开始失去光彩。根据数据公司 Syntun 的报告,在周四结束的“618”购物节期间,全网销售总额同比下降7%,至7430亿元人民币。研究公司 Feigua 的数据显示,5月下半月,中国“直播带货一哥”李佳琦的销售额同比下降46%,美妆主播骆王宇的销售额暴跌了68%……。

    +

    文推

    +

    性癖纵横观 I

    +

    性癖纵横观 II

    +

    你所熟知的时代,才开始没多久

    +

    只需一人努力,就可以让一个国家进入原始社会

    +

    “你是爸妈不要的孩子。” 送养的女孩被接回家后

    +

    思源字体背后的中国公司- 造福亿万国人,默默无闻 40 载,让中国字体走向世界

    +

    做好优化、选好软件,改善 Android 类原生 ROM 的使用体验

    +

    项目

    +

    VPS剩余价值计算器

    +

    gcop:Your git AI copilot.

    +

    GPT 学术优化 (GPT Academic)

    +

    ONLYOFFICE Docker部署

    +

    把主动权「完全」握在自己手里:HTML 个人电子工作台搭建指南

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-4/index.html b/public/weekly/zhoubao-4/index.html new file mode 100644 index 0000000..7d053cd --- /dev/null +++ b/public/weekly/zhoubao-4/index.html @@ -0,0 +1,231 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(四)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,每周四更新.

    +

    事记

    +

    一.日本政府宣布废除所有软盘使用规定

    +

    日本数字厅大臣河野在上月的发布会表示:“在 1,034 项法规中,我们已经完成了对 1,033 项要求通过软盘提交的法规的审查”,法规关于软盘的使用已全部废除。河野大臣表示,接下来还会推动废除传真机办公

    +

    二.最新的CVE漏洞目前严重影响了Open-SSH的安全性

    +

    SSH RCE: CVE-2024-638该漏洞是由于 OpenSSH 服务器 (sshd) 中的信号处理程序竞争问题,未经身份验证的攻击者可以利用此漏洞在 Linux 系统上以 root 身份执行任意代码。

    +

    影响版本:8.5p1 <= OpenSSH < 9.8p1

    +

    在我们的实验中,平均需要约 10,000 次尝试才能赢得这种竞争条件,因此每 120 秒 (LoginGraceTime) 接受 100 个连接 (MaxStartups) 需要约 3-4 小时。最终,平均需要约 6-8 小时才能获得远程 root shell,因为我们只有一半的时间可以正确猜出 glibc 的地址(由于 ASLR)。

    +
    +

    目前几个发行版的动静:

    +
    +
      +
    • Fedora: 💤 [9.6p1]
    • +
    • openSUSE: 几分钟前打了 patch [9.6p1],二进制包可能要稍晚更新;Leap 中 15.6 依旧 💤 [9.6p1]
    • +
    • ArchLinux: 推了 9.8p1-1
    • +
    • Ubuntu: 22.04-24.04 均已 backport [src]
    • +
    • Alpine: 💤 [9.7p1],因为人家用的是 musl 压根不受影响
    • +
    • Debian: bookworm 在 6/22 悄悄 backport 直到今日才推送 [9.2p1-2+deb12u3],sid 依旧有漏洞 [9.7p1-6]
    • +
    • NixOS: backport 了补丁 [9.8p1]
    • +
    • CentOS Stream: 💤 [9.6p1-1]
    • +
    • Gentoo: 已 backport [9.6p1,9.7p1]
    • +
    • openEuler: 💤 [9.3p2-3]
    • +
    • openAnolis: 💤 [9.3p2-1]
    • +
    • AOSC OS: 推了 [9.8p1]
    • +
    • Deepin: backport 了 [9.7p1-4deepin2]
    • +
    • openKylin: 💤 [9.6p1-ok4]
    • +
    • LoongnixServer: 不受影响 [8.0p1]
    • +
    • Loongnix: 不受影响 [7.9p1]
    • +
    +

    三.多款国内安卓系统设备名称联网校验

    +

    Android 系统里存在设备名称这个配置,它会作为蓝牙、Wi-Fi 热点网络共享的默认名称,展示给其他设备。并且会作为环境变量 Settings.Global.DEVICE_NAME,能被 App 读取。

    +

    2024年6月 下旬,真我(realme)手机在系统更新日志中提到:

    +
    +

    新增 更改手机名称联网校验功能,系统会检测手机名称是否存在敏感字符,校验未通过将无法保存或使用更改的手机名称

    +
    +

    根据 V2EX 上的讨论来看,小米手机也被添加了此限制。而造成此审查的直接原因,可能与限制 AirDrop 相同,都是在尝试管理「近距离自组网」

    +

    关于使用 Wi-Fi 名称来抗议,在俄罗斯存在类似的先例:2024年3月,一名学生将路由器的名称设置为:Slava Ukraini!(荣耀属于乌克兰!),如果有人在范围里检查 Wi-Fi 选项,就会看到这段口号。随后该学生在莫斯科被捕,法院以展示「极端主义组织标志」的罪名,判处其 10 天监禁,该学生随后还被莫斯科国立大学开除。

    +

    四.知乎加强爬虫限制

    +

    使用包含"bot"或"spider"的UA访问知乎时,页面的部分内容被替换为随机汉字

    +

    知乎在 robots.txt 中移除 Google 和 Bing 等搜索引擎后,近期又针对UA进行了严格的限制。目前,在 User Agent 中出现"bot"或"spider"的访问结果中,知乎会将问题或专栏的标题、发布者的用户名、文章正文等文本替换为随机汉字。必应的部分搜索结果已经受到了影响。

    +

    五.CentOS Linux 7 生命周期正式结束

    +

    此外,与 CentOS 7 同源的红帽企业 Linux 7(RHEL 7)也于今日进入 EOM 停止维护阶段,企业可通过 ELS 订阅付费获得额外 4 年的延长支持。

    +

    据介绍,CentOS 项目与红帽已于 2020 年结束 CentOS Linux 开发,将全部投资转向 CentOS Stream

    +
      +
    • +

      在 RHEL 新版本发布之前,红帽会在 CentOS Stream 上持续发布源代码,作为 RHEL 的上游开源开发平台

      +
    • +
    • +

      CentOS 创始人 Gregory Kurtzer 启动 Rocky Linux 项目,开发 RHEL 的下游二进制兼容版本

      +
    • +
    +

    六.亚马逊Kindle中国服务正式停止

    +

    据亚马逊中国官网消息,2024年6月30日起,Kindle中国电子书店停止云端下载服务,此后未下载的电子书将无法下载和阅读。同时,Kindle客户服务也将停止支持。

    +

    Kindle中国电子书店已于2023年6月30日停止运营。亚马逊建议用户及时将已购买电子书及其他Kindle内容下载至Kindle阅读器和Kindle App (含手机端和电脑端).

    +

    文推

    +

    置身事内 - 读书笔记

    +

    我们所认识的胡友平

    +

    是语言基于文字,还是文字基于语言?

    +

    066|真正松弛的感觉是:听从内心,去创造,去生活

    +

    项目

    +

    全栈 DS/DA 养成手册

    +

    网络信息安全从业者面试指南

    +

    Go 写的 VitePress 可视化配置工具

    +

    TradingView : 一个图表平台和社交网络,全球60M+交易员和投资者使用它

    +

    一个干净、深色的 Neovim 主题,用 Lua 编写,支持 lsp、treesitter 和许多插件

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-5/index.html b/public/weekly/zhoubao-5/index.html new file mode 100644 index 0000000..1ac69fa --- /dev/null +++ b/public/weekly/zhoubao-5/index.html @@ -0,0 +1,211 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(五)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,每周四更新.

    +

    事记

    +

    一.谷歌在Chromium中预留私有API以读取更多PC硬件信息

    +

    谷歌在Chromium开源项目中预留了私有API,允许谷歌网站读取PC的CPU/GPU使用率、内存使用率等硬件信息。这些API仅对谷歌主域名开放,可能违反了欧盟的数字市场法案(DMA),并可能构成不公平竞争。例如,Google Meet可以利用这些信息优化视频会议性能,而竞争对手如Zoom则无法获取同样级别的硬件信息。

    +

    此外,这些API通过一个Chrome扩展程序实现,用户无法禁用或在扩展管理页面中找到。Microsoft Edge和Brave浏览器也被发现内置了该扩展程序。目前尚不清楚谷歌是否会更新Chrome以允许用户禁用此扩展。

    +

    V2EX站友表示,插件远比网页的级别高,可调用资源甚至接近浏览器的级别,可用来收集用户的硬件画像,对保护隐私极其不利。

    +

    二.中国取证公司五五安科旗下昆仑解锁实验室发布Android14提权取证工具

    +

    厦门五五安科信息科技有限公司的昆仑解锁实验室最近发布了一款面向Android 14的提权取证工具。此工具据推测通过利用漏洞绕过了Android权限管理机制,从而访问和提升设备权限,实现对设备的深入取证。特别值得注意的是,该工具成功实现了对采用Google Tensor芯片的Pixel手机的权限提升。据悉,此漏洞可能已由Google在其七月份的安全更新中得到修复,然而目前尚不明确该取证工具是利用已知漏洞还是未公开的新漏洞进行提权。鉴于此,建议所有用户更新至最新的安全补丁,以确保设备安全。

    +

    三.两部门:开展“网络去 NAT”专项工作,进一步深化 IPv6 部署应用

    +

    工信部办公厅、网信办秘书局近日发布《关于开展“网络去 NAT”专项工作,进一步深化 IPv6 部署应用的通知》。

    +
      +
    • 基础电信企业要增加 IPv6 互联网专线产品供给,新增互联网专线默认开通 IPv6 功能。要加快实施家庭网关 IPv6 地址前缀二次分发功能升级
    • +
    • 到 2024 年底,基础电信企业自有环境固定宽带用户 IPv6 连通率不低于 80%。终端设备制造企业要严格落实无线电发射设备型号核准有关通知要求。各省(区、市)有关部门要推动属地终端设备制造企业加快存量家庭无线路由器 IPv6 功能升级
    • +
    • 互联网企业要深化应用服务 IPv6 升级改造,优化放量引流策略,实现注册、登录、使用全链条支持 IPv6,提升固网环境下 IPv6 流量占比。
    • +
    • 内容分发网络(CDN)运营企业要推动边缘节点、核心节点等各层级支持 IPv6,提升用户加速、业务调度和内容回源等 IPv6 流量占比。
    • +
    • 云服务企业要优化产品业务逻辑,向用户提供服务时默认启用 IPv6 功能
    • +
    +
    +

    盘点一下国内 IPv6 发展过程中都折腾了啥

    +
    +

    四.小米采取措施禁止国行设备运行国际版系统

    +

    近日,知名官改 ROM Xiaomi.EU 的测试者 Kacper Skrzypek 在 X 发文[1]称,小米在开机向导中添加了区域检测机制。

    +

    如果设备硬件为国行版,但正在运行国际系统,将无法完成开机向导,并提示「Unsupported software」。

    +

    原推文提醒,该机制目前已在 Redmi Note 13 系列实装。

    +

    五.30年来首次 我国新设六个国际通信业务出入口局

    +

    工业和信息化部7月10日向中国电信、中国移动、中国联通颁发许可,批复在广西南宁、山东青岛、云南昆明、海南海口设立国际通信业务出入口局。

    +

    1994年,我国全功能接入国际互联网,中国电信、中国移动、中国联通在北京、上海、广州设立了9个国际通信业务出入口局,实现公众互联网与国际互联网连通。

    +

    广西南宁、山东青岛、云南昆明、海南海口新增设6个国际通信业务出入口局,这是30年来首次增设,建成后将显著提升国际网络通信能力,更好推动基础设施互联互通、数据跨境流动和国际数字贸易发展,促进更高水平开放,为构建新发展格局塑造新动能新优势。

    +

    目前已知的登陆站应该是青岛、汕头、上海,以及福州的淡福海缆, 似乎是湾专线、以及通信业务才用的,还有厦金海缆,不过这些都不给宽带业务用。

    +
    +

    文推

    +

    唐一水|谁能躲过搀煤的食用油?

    +

    乔姆斯基谈语言的差异,演化及纯正性

    +

    西安男子开民办派出所和警察抢生意 半年赚百万

    +

    Git 的故事:這一次沒這麼好玩 | 軟體考古學家

    +

    不愿被困住的青年教师,逃离“非升即走” | 谷雨

    +

    爱宠死了但我仍在偿还狗狗的医疗费用动物医疗会成为下一个吸血产业吗

    +
    +

    项目

    +

    命令行 Git 信息工具

    +

    IOT 固件安全 All in One

    +

    Typikon:使用 markdown 来编写您的在线书

    +

    推荐系统入门指南,全面介绍了工业级推荐系统的理论知识

    +

    史上最大密码泄露下载-RockYou2024 密码汇编泄露近 100 亿

    +

    由 BTN 网络统计分析/用户报告得出的可被安全的加入系统防火墙屏蔽的 IP 地址列表

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-6/index.html b/public/weekly/zhoubao-6/index.html new file mode 100644 index 0000000..3aa4288 --- /dev/null +++ b/public/weekly/zhoubao-6/index.html @@ -0,0 +1,195 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(六)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,每周四更新.

    +

    事记

    +

    一.NVIDIA 全面转向开源 GPU 内核模块

    +

    NVIDIA 于 2022 年 5 月发布了一组 Linux GPU 内核模块,作为具有双重 GPL 和 MIT 许可的开源模块。当时该公司宣布,NVIDIA 开放内核模块最终将取代闭源驱动程序。现在,由于开源 GPU 内核模块实现了同等甚至更好的应用程序性能,NVIDIA 将在即将发布的 R560 驱动程序版本中完全过渡到开源 GPU 内核模块

    +

    对于 Grace Hopper 或 Blackwell 等最新平台,用户必须使用开源 GPU 内核模块,这些平台不支持专有驱动程序。对于 Turing、Ampere、Ada Lovelace 或 Hopper 架构的较新 GPU,NVIDIA 建议切换到开源 GPU 内核模块。对于 Maxwell、Pascal 或 Volta 架构的较旧 GPU,开源 GPU 内核模块与平台不兼容,将继续使用 NVIDIA 专有驱动程序。

    +

    二.代码托管平台 GitLab 正考虑出售,目前市值约 80 亿美元

    +

    GitLab 于 2021 年在美股上市,现在的股价不到上市时的一半,仅 2024 年就下跌了 16%。

    +

    尽管该公司报告称,其收入同比增长 33%,达到 1.692 亿美元,并在最新季度首次实现正现金流,但它承认,由于与微软旗下github的竞争,其产品定价面临阻力。

    +

    根据 GitLab 国内官网介绍,许多知名企业均有使用该公司服务,包括中国联通、中国电信、英特尔、网易、理想、蔚来等

    +

    三.家电翻新机背后的秘密:伪造能效标识、化学剂漂白外壳

    +

    今年以来,国家推动新一轮家电以旧换新,引导完善废旧家电回收体系。不过,私拆、翻新机目前仍然大量存在,翻新机已是业内公开的秘密,它存在一条隐形的产业链。不久前格力电器董事长兼总裁董明珠在格力电器股东大会上说,有的废旧空调,被不良商家几百元收回来,翻新后1500元卖出去,消费者是最大的受害者。

    +

    四.中国气象局:“闪信”等强制提醒技术落地防灾减灾一线

    +

    今年以来,浙江省气象局基于省突发事件预警信息发布系统对接“闪信”发布渠道,针对三家运营商“霸屏”业务要求的区别,实现快速自动编辑、一键式推送发布功能。在发布气象预警信息时,“闪信”还可与浙政钉信息、短信、应急广播信息等原有渠道一并通过该系统一键发布。

    +
    +

    PS:0级短信早该用来预警了,有些地方却用来发广告;而且这种事居然没有全国统一...

    +
    +
    +

    文推

    +

    性癖纵横观VI

    +

    2024年上半年互联网黑灰产研究报告

    +

    供应链投毒后,我们的选择还剩下哪些?

    +

    条形码和二维码是如何颠覆现代商业世界的?

    +

    终于可以在 Linux 下愉快打印了:Linux 发行版配置打印机攻略

    +
    +

    项目

    +

    一款开源的跨平台剪切板管理工具

    +

    一个高度可定制的变更日志生成器,遵循传统提交规范

    +

    收录了一些能够免费下载油管、B 站、抖音等平台视频的下载工具

    +

    一款以图形为中心、轻量级、本地优先的用于构建第二大脑的效率工具

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-7/index.html b/public/weekly/zhoubao-7/index.html new file mode 100644 index 0000000..489368c --- /dev/null +++ b/public/weekly/zhoubao-7/index.html @@ -0,0 +1,188 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(七)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章,每周四更新.PS:因为昨天输入法突发恶疾,所以无法按时更新。

    +

    事记

    +

    一.瑞士强制要求所有政府软件开源

    +

    瑞士通过了名为《联邦电子政务法》(EMBAG)的立法,强制要求所有公共部门使用 开源 软件 (OSS)。 该法律规定,除非涉及第三方权利或安全问题,否则所有公共机构必须公开其开发或为其开发的软件的源代码。这一举措旨在提高政府运营的透明度、安全性,和效率。

    +

    二.Microsoft 推出 26100.1297 版本,为中国设备安装了 Microsoft 电脑管家

    +

    三.360推出AI弹窗过滤器可以屏蔽自家弹窗 30元/月

    +

    360 在测试新功能名为 AI 弹窗过滤器,可以拦截用户电脑上包括但不限于360 自家的弹窗广告。

    +

    原来的360弹窗过滤器无法过滤360自家的弹窗广告。此功能包含在360AI大会员中,30元每月。

    +

    并且暂时还不清楚能否彻底拦截 360 全家桶的所有弹窗广告。

    +

    四.Windows 全球大规模蓝屏,疑因 CrowdStrike 推送补丁导致

    +

    有大量网友在微博、X、reddit等社交媒体上反馈自己工作的 Windows 电脑出现蓝屏,疑似因为 CrowdStrike 的 csagent.sys 导致的。

    +
    +

    文推

    +

    2023 年终总结 | 要让生活「自洽」

    +

    我知道的关于 Git 提交的 89 件事

    +

    洗个澡我操碎了心·淋浴间安装设计DIY全分享

    +
    +

    项目

    +

    解决 windows 打游戏卡输入法的问题

    +

    从零开始搭建你的免费博客评论系统(Remark42 + fly.io)

    +

    资源整合,下载不求人!NAS搭建磁力搜索网站程序——Bitmagnet-Next-Web

    +

    群晖DSM使用qBittorrent+蜜柑计划+nastool实现自动追番和入库emby/jellyfin

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-8/index.html b/public/weekly/zhoubao-8/index.html new file mode 100644 index 0000000..1be5159 --- /dev/null +++ b/public/weekly/zhoubao-8/index.html @@ -0,0 +1,202 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(八)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +

    事记

    +

    一.中国就“网号”“网证”征求意见

    +

    中国发布《国家网络身份认证公共服务管理办法》征求意见稿。截至日期8月25日。办法中提到,自然人在互联网服务中依法需要登记、核验真实身份信息时,可通过国家网络身份认证 App 自愿申领并使用“网号”“网证”进行非明文登记、核验,无需向互联网平台等提供明文个人身份信息。由此,可以最大限度减少互联网平台以落实“实名制”为由超范围采集、留存公民个人信息。不满十四周岁的自然人需要申领网号、网证的,应当征得其父母或者其他监护人同意。互联网平台不得要求用户另行提供明文身份信息。

    +

    记者注意到,申领和使用“网号”“网证”的应用“国家网络身份认证App(认证版)”已在多个应用商店上线。此前,中国公安部、网信办等研究起草了征求意见稿,核心是“为自然人提供申领网号、网证以及进行身份核验等服务。”根据反馈,申领注册“网号”“网证”需要使用身份证,人脸识别是否为本人,关联手机号,设置网络身份口令,授权网络身份在用户手机使用。目前,正处于试点阶段,已上线试点APP和场景共67个,如国家政务服务平台、中国铁路12306、淘宝、微信、小红书、QQ等。据悉,后续,有关主管部门还将继续研究适用的应用场景,包括互联网用户账号实名注册、登录,对存在涉诈异常账号的用户身份重新进行核验,网上办理政务服务事项时的身份核验等。

    +
    +

    乍一看似乎还行,然后就想到根据网号一键封禁所有账号的操作,以及新的拖库危机

    +
    +

    二.全国地震预警小程序公测启动

    +

    中国地震台网中心、中央广播电视总台国家应急广播与腾讯合作,推出了全国微信预警服务的公测版本。该小程序与此前江苏地震预警服务UI完全一致,自行选择即可。

    +

    可通过微信搜索"中国地震台网"或"地震预警",进入小程序并开启服务,接收官方地震预警信息。小程序支持高并发量用户秒级消息推送,并在地震发生时提供强提醒警示及防震指南。

    +
    +

    PS:依然是先试点再推广的流程,不过说好的0级短信呢。。。

    +
    +

    三.印尼因赌博和色情问题禁用搜索引擎 DDG

    +

    印尼通信部周五表示,已禁止以隐私为导向的搜索引擎 DuckDuckGo,理由是担心它可能被用来访问该国非法的色情和在线赌博网站。印尼是全球穆斯林人口最多的国家,该国制定了严格的规定,禁止在网上分享被视为淫秽的内容。通信部官员乌斯曼·坎松告诉路透社,DuckDuckGo 被屏蔽“是因为很多人投诉其搜索结果中充斥着网络赌博和色情内容”。印尼近几个月来誓言要严厉打击网络赌博,并禁止访问多个此类网站。尽管网络赌博属于非法,但政府数据显示,去年有300万印尼人上网赌博,花费约200亿美元,约占国内生产总值的1.5%。

    +
    +

    群友:建议安装反诈APP,最好使用鸿蒙系统内置

    +
    +

    四.DigiCert 吊销数万份使用 CNAME 进行域名验证的 TLS/SSL证书

    +

    数字证书颁发机构 DigiCert 在 7 月 29 日通过博客宣布将吊销没有适当域控制验证 (DCV) 的证书,大约 0.4% 的 DigiCert 适用域验证受到影响,数量可能超过数千份。根据严格的 CABF 规则,域验证中存在问题的证书必须在 24 小时内撤销,​​无一例外。DigiCert 已通知受影响的客户,他们必须在 24 小时内更换证书。

    +

    本次事件涉及通过添加 DNS CNAME 记录,并为此提供随机值进行域名控制验证。其中一种方法要求随机值以下划线字符为前缀,下划线前缀可确保随机值不会与使用相同随机值的实际域名发生冲突。最近,DigiCert 发现在某些基于 CNAME 的验证案例中使用的随机值中没有包含下划线前缀。虽然域名发生冲突的可能性实际上可以忽略不计,但如果验证不包含下划线前缀,则仍被视为不合规。DigiCert 表示,“CABF 认为任何与域验证有关的问题都是严重问题,需要立即采取行动。”

    +
    +

    文推

    +

    Web App: 从 HTML 到 Jamstack

    +

    我是如何停止担心并喜欢 Makefiles 的

    +

    分享个人软路由、NAS 和家庭服务器的使用情况

    +

    拆解报告:DELTA台达HVP系列高压直流电源DPR240/50A整流模块

    +

    【瞭望】海航重整案——亚洲规模最大、最难、最复杂的重整案件是如何炼成的

    +
    +

    项目

    +

    开发者文档合集

    +

    运维开发绿皮书

    +

    各个 linux 发行版在线试用

    +

    程序员专属SSH聊天室 devzat

    +

    公务员从入门到上岸,最佳程序员公考实践教程

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/weekly/zhoubao-9/index.html b/public/weekly/zhoubao-9/index.html new file mode 100644 index 0000000..964b7ac --- /dev/null +++ b/public/weekly/zhoubao-9/index.html @@ -0,0 +1,191 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + +
    + +
    + +

    谈天说地:狄奇周刊(九)

    + + + + +
    +

    前言 这里是Dich的周刊,通过博客的形式讲述每周互联网形势,以及分享一些文章。

    +

    事记

    +

    一.威瑞信宣布.COM域名将于9月1日起涨价

    +

    运营 .COM 的域名注册局威瑞信将于9月1日将批发价从9.59美元提高到10.26美元。大多数域名注册商都会在此基础上加价,但有些注册商会向客户收取批发价。因此,许多注册商都会提高价格。这是 .COM 域名价格连续第四年上涨7%,这是威瑞信与互联网名称与数字地址分配机构签订的合同以及与美国政府达成协议允许的最高涨价幅度。总而言之,自四年前以来,威瑞信已将 .COM 域名批发成本提高了31%。对于域名注册者来说,好消息是威瑞信未来两年内不得涨价。但此后该公司可以连续四年每年涨价7%。

    +

    二.微软 Authenticator 应用被曝设计缺陷,账号被覆盖、锁定

    +

    微软的 Microsoft Authenticator 身份验证应用存在设计缺陷,用户在扫描QR码添加新账号后,应用会覆盖之前的账号,导致多重身份验证(MFA)被锁定。

    +

    这个问题的核心在于,Microsoft Authenticator 会用相同的用户名覆盖账户。由于多数用户的用户名是电子邮件地址,这个问题尤为严重。

    +

    而Google Authenticator等应用通过添加银行、汽车公司等信息来避免此问题。覆盖账号后,系统难以识别哪个账号被覆盖,可能导致新旧账号均出现验证问题。用户可能在几周或几个月后才发现账号被注销。

    +

    三.马来西亚正在强制劫持 DNS 请求以阻止用户访问被屏蔽的网站

    +

    马来西亚互联网服务提供商 (ISP) 似乎实施了透明 DNS 代理,即强制所有互联网流量返回到其本地 DNS,即使使用谷歌和 Cloudflare 等替代 DNS 也是如此。实施该策略的 ISP 包括 Time、Maxis、U Mobile、CelcomDigi 和 Unifi。通过透明 DNS 代理,ISP 可以拦截并重定向 DNS 请求至本地 DNS。

    +

    为了遵守规定,所有电信公司/互联网服务提供商都必须通过其本地 DNS 阻止被认定为违法的网站。目前尚不清楚这项针对本地服务的透明 DNS 代理实施时间,但由于已有四家以上的电信公司实施,因此这似乎是针对所有电信公司的全国性指令。据称该指令早在今年2月就已发布。 马来西亚监管机构尚未对此有关的询问作出回应。

    +

    —— SoyaCincau、Sinarprojec

    +

    四.1Password发现高危安全漏洞,Mac用户需立即升级到最新版本

    +

    知名密码管理器1Password的Mac版本被发现存在一个高危安全漏洞,该漏洞允许恶意软件绕过进程间的通信保护,窃取用户的解锁密钥。

    +

    这一安全问题由参与DEFCON黑客大赛的安全研究人员发现,并计划在一次演讲中公开。1Password已经收到通知并及时修复了这一漏洞,敦促用户升级到8.10.38或之后的版本以确保安全。

    +

    该漏洞被标识为CVE-2024-42219,目前没有证据表明它已被恶意黑客利用,更多关于该漏洞的细节将在DEFCON大会上演讲后公布。

    +

    文推

    +

    当你不再是宇宙的正中央

    +

    你在电脑上看到的字到底是怎么显示出来的?

    +

    放轻松 | 治愈「被互联网影响的心智」

    +
    +

    项目

    +

    将你的 Telegram Channel 转为微博客

    +

    FList:静态页面生成的一个简洁的在线文件列表

    +

    互联网仍有记忆!那些曾经在校招过程中毁过口头offer、意向书、三方的公司

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/windows-activation/index.html b/public/windows-activation/index.html new file mode 100644 index 0000000..fbebc9a --- /dev/null +++ b/public/windows-activation/index.html @@ -0,0 +1,366 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + +
    + + +
    + +
    + +

    乱七八糟:Windows激活那些事

    + + + + + + +
    +

    前言 Windows的正版售价十分昂贵,2025年的今天大部分人都使用着OEM厂商自带的windows系统或自己想办法激活,那么,激活到底是什么原理?

    +

    一.分类:功能与渠道

    +

    一般情况下,提到Windows和Office的版本,是按功能分类的,如:

    +
      +
    • 标准版(Standard)
    • +
    • 初级版(Starter)
    • +
    • 家庭基础版(Home Basic)
    • +
    • 家庭高级版(Home Premium)
    • +
    • 专业版(Professional)
    • +
    • 企业版(Enterprise)
    • +
    • 旗舰版(Ultimate)
    • +
    • 教育版(Education)
    • +
    • 移动版(Mobile)等等。
    • +
    +

    在按功能划分的基础上,根据销售渠道又细分出以下几种不同版本,激活方式与之对应,激活原理也各不相同:

    +
      +
    • 零售版(Retail):个人单独购买,一般是盒装光盘,配发一个激活码;
    • +
    • 批量版(VOL,Volume Licensing for Organizations):企业批量购买,提供了方便大量激活的方案;
    • +
    • 厂商版(OEM,Original Equipment Manufacturer):随电脑整机附赠,主板BIOS内嵌激活信息;
    • +
    +
    +

    二.激活方法和原理

    +

    零售(Retail)激活

    +

    零售版 Windows 和 Office 的激活机制可以通俗地类比为在商店购买记事本:用户支付费用获得记事本,如何使用由用户决定。

    +
      +
    • +

      试用期与激活码输入
      +安装零售版后,系统会有一段试用期。用户需进入激活界面,输入零售版激活码。激活组件会验证激活码的正确性,并根据激活码和硬件信息生成 Installation ID(IID)。

      +
    • +
    • +

      激活方式

      +
        +
      • 网络激活:系统自动将 IID 发送至微软服务器,服务器校验后生成 Confirmation ID(CID)并返回,激活组件完成验证后激活成功。
      • +
      • 电话激活:用户拨打微软电话,手动输入 IID,并根据语音提供的 CID 填入激活界面完成激活。
      • +
      +
    • +
    • +

      服务器记录与限制
      +微软服务器会记录硬件信息和激活码信息。如果激活码使用次数过多,可能被限制为仅电话激活;若激活的电脑数量超标,则激活码会被封禁,无法再使用。尽管微软封禁激活码,但违规泄露的新激活码常被二手商以低价出售。

      +
    • +
    • +

      激活机制的技术特性
      +零售版激活依赖微软服务器的校验,采用不对称加密技术:公钥在系统中,私钥在服务器上。用户只能校验 CID,无法从 IID 计算 CID。这使得激活必须经过服务器验证。

      +
    • +
    • +

      盗版激活手段

      +
        +
      • 购买盗版激活码:通过二手商获取违规泄露的激活码。
      • +
      • 暴力破解:修改系统激活组件绕过校验,但更新可能导致破解失效,且可能影响系统稳定性,因此已逐渐被淘汰。
      • +
      +
    • +
    +

    VOL激活

    +

    VOL版有两种激活方式:一种是MAK激活(Multiple Activation Key),另一种是KMS激活(Key Management Service)。

    +
      +
    • +

      MAK激活流程: MAK激活的流程类似于零售版,但激活码属性有所不同。每个 MAK 激活码预设了有限的可用次数,可以用于激活任意数量的电脑。

      +
        +
      • 用户输入 MAK 激活码。
      • +
      • 系统通过网络向微软服务器发送激活请求。
      • +
      • 微软服务器返回 CID 并完成激活,同时将激活码的可用次数减 1。
      • +
      +
    • +
    • +

      特点

      +
        +
      • 激活码的使用次数有限,用尽后激活码失效。
      • +
      • 激活成功后永久生效,无需重新激活。
      • +
      • MAK 激活码常因违规泄露成为盗版交易的高风险区。
      • +
      +
    • +
    • +

      KMS激活流程: KMS 激活通过本地搭建的激活服务器实现,适合需要批量激活的企业或大规模组织。

      +
        +
      • 系统管理员搭建 KMS 服务器(激活服务端)。
      • +
      • 客户端输入 KMS 激活码(GVLK)并配置 KMS 服务端地址。
      • +
      • 客户端发送包含系统版本、激活码信息、硬件信息等内容的激活请求到服务器。
      • +
      • 服务器校验激活请求并返回激活结果。
      • +
      • 客户端读取结果,完成激活。
      • +
      +
    • +
    • +

      特点

      +
        +
      • 可以自行搭建激活服务器;
      • +
      • 激活有效期为 180 天,到期后需重新激活。
      • +
      • 适用于局域网环境,可通过 KMS 批量管理客户端设备。
      • +
      +
    • +
    +
    +

    没有花钱购买微软授权,擅自使用KMS激活仍是盗版,个人使用微软懒得管,企业这么搞会吃官司。

    +
    +
    +

    弊端就是:必须每180天再激活一次;成功激活后,你的电脑就会变成团队电脑。KMS工具开发者就是管理员。不要不以为然,管理员能够执行的操作权限非常高,拷贝个数据收集个信息简直是小菜一碟,更厉害的还能直接reset你的系统而保留KMS的权限。说不定,哪天KMS的开发者不开心,就帮你清空一下电脑。

    +
    +

    OEM激活

    +

    OEM激活(Original Equipment Manufacturer)是三种激活方式中最特殊的,因为它完全脱离了联网认证,实现了高度绑定于硬件的激活机制。

    +
      +
    • +

      OEM激活机制:生产厂商在主板 BIOS 芯片中加入 SLIC 信息(Software Licensing Internal Code),同时在操作系统中预装对应的厂商证书和一个 OEM 激活码

      +
        +
      • 当电脑启动时,BIOS 会将 SLIC 信息加载到内存。
      • +
      • 操作系统接管后,从内存中读取 SLIC 数据,与厂商证书和激活码进行匹配验证。
      • +
      • 验证通过后,系统被视为已激活,无需联网认证。
      • +
      +
    • +
    • +

      特点

      +
        +
      • 激活严格绑定硬件(主板)。
      • +
      • 不需联网认证,减少了服务器交互过程。
      • +
      • 系统重装后仍能自动激活,只要硬件没有更改。
      • +
      +
    • +
    • +

      破解与改装方法:由于 OEM 激活省略了联网步骤,激活逻辑被高度依赖硬件信息,这也给破解提供了多个切入点:

      +
        +
      • +

        硬改流

        +
      • +
      • +

        直接刷写主板 BIOS,将 SLIC 信息写入其中,使主板伪装成具备 OEM 激活能力的硬件。缺点:风险较高,操作不当可能损坏 BIOS,导致主板无法启动。

        +
      • +
      • +

        暗改流

        +
      • +
      • +

        找到内存中存储 BIOS 数据的位置,将 SLIC 信息直接注入内存。优点:无需修改主板 BIOS,操作更灵活。缺点:仅在系统运行时生效,重启或关机后需重新注入。

        +
      • +
      • +

        破解流

        +
      • +
      • +

        修改操作系统读取 BIOS 数据的逻辑,让系统从伪造的 SLIC 数据中完成验证。

        +
      • +
      • +

        配合导入对应的厂商证书和 OEM 激活码,实现伪装成 OEM 激活。操作相对简单,适用于多种硬件。缺点:可能影响系统稳定性,且破解工具质量参差不齐。

        +
      • +
      +
    • +
    +

    数字权利激活

    +

    微软在 Windows 10 中推出了全新的激活方式——数字激活(Digital License Activation)。这种激活方式彻底改变了传统激活依赖激活码或联网验证的逻辑,通过绑定硬件信息和微软账户,为用户提供更加便捷的体验,同时也带来了新的破解手段。

    +
      +
    • +

      数字激活的原理

      +
        +
      • 用户需通过传统方式(如零售版激活、MAK激活、OEM激活)激活系统。
      • +
      • 激活成功后,系统会将电脑硬件信息(HWID)、激活凭证和微软账户绑定。
      • +
      • 激活凭证会上传至微软服务器,记录为永久激活状态。
      • +
      • 以后在同一台电脑上重装系统时,只需登录微软账户,系统即可自动完成激活。
      • +
      +
    • +
    • +

      特点

      +
        +
      • 激活状态与电脑硬件绑定,与激活码无直接关系。
      • +
      • 用户无需保留激活码或再次手动激活,方便重装系统。
      • +
      • 对硬件改动较大(如更换主板)时,需重新激活。
      • +
      +
    • +
    • +

      数字激活的漏洞利用

      +
    • +
    +

    微软为支持用户从低版本(如 Win7/Win8)升级到 Win10,引入了系统升级继承激活状态的规则,这成为数字激活漏洞的核心:如果升级前的系统已经激活,无论激活手段是否合法,升级后的 Win10 系统都会继承激活状态。即使此前是通过盗版手段激活的系统,也能顺利完成升级并绑定数字激活状态。

    +
      +
    • +

      关键组件:gatherosstate.exe

      +
        +
      • 此组件在升级过程中验证当前系统是否激活。
      • +
      • 验证通过后,生成一份与电脑硬件相关的 GenuineTicket.xml 文件,包含 HWID(Hardware Identifier)等信息。
      • +
      • 升级后的系统会导入该文件,将激活信息绑定至微软服务器,实现数字激活。
      • +
      +
    • +
    • +

      数字激活的破解演变

      +
        +
      • +

        手动操作版本:从 Win10 安装包中提取 gatherosstate.exe,将其放到 Win7/Win8 系统中,利用任何激活手段(如 OEM 激活或暴力破解)骗过 gatherosstate,生成 GenuineTicket.xml。在 Win10 系统中导入该文件,重启联网,即可激活系统。

        +
      • +
      • +

        进阶版数字激活工具:集成破解的激活组件(如 slc.dll),跳过预先激活 Win7/Win8 的步骤,直接生成 GenuineTicket.xml。本质等同于暴力破解,只是流程更加自动化。

        +
      • +
      • +

        HWID Key 的出现:经过逆向分析,发现 gatherosstate.exe 完全在本地运行,生成 HWID 的算法无需联网验证。专业人士破解并提取了生成 HWID 的算法,开发出 HWID Key 工具,能够在任意电脑上生成有效的 HWID 并完成数字激活。用户无需再通过升级路径或手动操作,随时随地实现数字激活。

        +
      • +
      +
    • +
    +
    +

    最新消息,MAS团队破解了SSP,现在可以使用TSforge来激活自 Windows 7 以来每个版本的 Windows 的每个版本,以及自 Office 2013 以来的每个 Windows 插件和 Office 版本!

    +
    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/windows-all/index.html b/public/windows-all/index.html new file mode 100644 index 0000000..f668ed7 --- /dev/null +++ b/public/windows-all/index.html @@ -0,0 +1,355 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + +
    + + +
    + +
    + +

    乱七八糟:Windows安装与环境配置

    + + + + + + +
    +

    前言 由于厂商默认安装windows家庭版导致各种问题频发,这里对 widnows 安装做一个总结,以及附上我个人的windows配置。

    + +
    +

    从官方安装:从微软官网下载镜像或MAS镜像站下载。

    +
    +
    +

    从Dichos安装,参考乱七八糟:Windows封装与全自动安装

    +
    +
    +

    二者都基于专业工作站版本,区别在于Dichos通过预应答文件和封装完成了许多设置与优化。Windows最新版本往往Bug比较多,推荐用上一版本;如最新版本为24H2,则推荐使用23H2.

    +
    +

    大版本分类

    + + + + + + + + +
    分类消费者版(Consumer)商务版(Business)物联网版(IoT)长期服务版(LTSC)
    目标用户家庭用户、个人消费者企业、机构、教育用户嵌入式设备、工业控制、POS、医疗设备等关键任务系统、长期稳定运行的设备
    主要版本Windows Home、Home Single Language、EducationWindows Professional、Enterprise、EducationWindows IoT Core、IoT Enterprise、IoT Enterprise LTSCWindows Enterprise LTSC、IoT Enterprise LTSC
    预装应用包含 Microsoft Store、娱乐和社交类应用精简部分消费类应用,保留企业管理工具极度精简,移除大部分消费类应用移除 Microsoft Store、Cortana 等非必要功能
    更新策略定期推送功能和安全更新可由企业控制更新策略,支持延迟功能更新可选择常规更新或 LTSC 版本,更新策略灵活仅推送安全补丁和关键修复,无新功能更新
    支持周期通常为 18 个月通常为 18~30 个月,取决于版本和配置IoT Enterprise LTSC 支持周期可达 10~15 年通常为 5 年主流支持 + 5 年扩展支持,共 10 年
    授权方式零售授权,需在线激活批量许可(Volume Licensing)、OEM 授权OEM 授权,适用于特定硬件设备批量许可,适用于特定行业和关键任务设备
    适用场景日常办公、娱乐、学习企业办公、教育机构、专业工作站工业自动化、零售终端、医疗设备等嵌入式系统医疗设备、金融终端、工业控制系统等需长期稳定运行的环境
    +
    +

    安装完成后的优化:

    +
    +

    一.设备级:

    +
      +
    • 关闭 BIOS 安全启动,快速启动
    • +
    • 解锁 BitLocker
    • +
    • 删除 OEM 分区,恢复简洁的设备分区
    • +
    +

    二.系统级:

    +
      +
    • 家庭版升级为专业工作站版
    • +
    • 将用户名改为非中文
    • +
    • 退出云端账号,杀死家庭组策略
    • +
    • 激活 Windows 与 MS office
    • +
    • 停止自动更新并恢复单级菜单
    • +
    +

    三.驱动级:

    +

    驱动的安装没有集成在Dichos中,而是作为手动安装的一部分避免出错。如自带系统有驱动包,先进系统拿出然后再安装新系统;一般来说,包括:

    +
      +
    • 主板驱动和CPU驱动;
    • +
    • 显卡驱动(独显/核显);
    • +
    • Wifi网卡驱动和蓝牙驱动;
    • +
    • 声卡驱动;
    • +
    • 硬盘驱动(较少见);
    • +
    • Fn快捷键驱动(厂商自带);
    • +
    • 笔记本自带的其他某某中心/管家(不建议使用)
    • +
    +

    而根据来源,又可以分为公版/通用驱动笔记本厂商特调/专用驱动,一般而言装公版驱动即可,保持通用性;如果你是重度游戏玩家则可以考虑特调驱动。

    +

    常用驱动下载网站

    + + + + + + + + +
    分类名称下载
    综合驱动天空链接
    厂商吾空链接
    厂商华硕链接
    厂商联想链接
    三大件AMD链接
    三大件Intel链接
    三大件NVIDIA链接
    +

    四.软件级:

    +
      +
    • 删除自带牛马以及不必要的管家类软件.
    • +
    +

    软件

    + +
    +

    这里说一下Rime输入法在Windows端叫小狼毫,输入方案用的是雾凇拼音 ,在获取更多输入方案中命令行输入iDvel/rime-ice:others/recipes/full安装。

    +
    +
    +

    传统意义上的三大件包括浏览器,编辑器以及密码管理器。

    +
    +

    五.设置级

    +
      +
    • 设置简洁高效的浏览器
    • +
    • 优化桌面布局与任务栏布局
    • +
    • 关闭开机自启软件
    • +
    • 关闭 Windows Defender 等烦人的通知
    • +
    +

    六.测试级(可选)

    +
      +
    • 查看PC型号与配置是否相同
    • +
    • 测试GPU/CPU/硬盘速率与使用时间
    • +
    • 屏幕坏点/喇叭/蓝牙检测
    • +
    • 网络测速
    • +
    +
    +

    开发环境

    +

    搭建虚拟机环境

    +
      +
    • Hyper-V
    • +
    +

    在 BIOS 中找到类似Intel VT-x”、“AMD-V”或“Virtualization Technology的选项,确保它是“Enabled”(启用)。随后按下 Win + S,输入“打开或关闭 Windows 功能”,在弹出的窗口中,找到 Hyper-V并启用,重启后即可出现。

    +
      +
    • VMware
    • +
    +

    首先下载 Vmware,随后安装并激活,然后提前下载好所需系统的镜像,这里推荐整合镜像站,并在Vmware中启动。

    +
      +
    • Virtulbox
    • +
    +

    直接到官网下载并安装。

    +
      +
    • WSL
    • +
    +

    控制面板->程序->启用或关闭Windows功能,选中适用于Linux的Windows子系统和虚拟机平台,待安装完成后重启电脑。

    +

    然后,在管理员模式下打开 PowerShell 或 Windows 命令提示符,方法是右键单击并选择“以管理员身份运行”,输入以下命令,然后重启计算机。

    +
    wsl --install
    +
    +

    此命令将启用运行 WSL 并安装 Linux 的 Ubuntu 发行版所需的功能。(可以更改此默认发行版)。

    +
    +

    使用 qemu-img 进行各种虚拟机格式转换

    +
    +
      +
    • qcow2 转 vmdk(VMware)
    • +
    +
    qemu-img convert -f qcow2 -O vmdk input.qcow2 output.vmdk
    +
    +
      +
    • qcow2 转 vdi(VirtualBox)
    • +
    +
    qemu-img convert -f qcow2 -O vdi input.qcow2 output.vdi
    +
    +
      +
    • qcow2 转 vhdx(新版 Hyper-V)
    • +
    +

    目前 qemu-img 不能直接输出 vhdx,但你可以先转成 vhd,再用微软工具(如 Convert-VHD)转换为 vhdx:

    +
    Convert-VHD -Path "output.vhd" -DestinationPath "output.vhdx" -VHDType Dynamic
    +
    +
      +
    • vmdk转vhdx
    • +
    +
    qemu-img convert -f vmdk -O vhdx input.vmdk output.vhdx
    +
    +
      +
    • vhd转vhdx +在 PowerShell 中执行以下命令:​
    • +
    +
    Convert-VHD -Path "C:\路径\源文件.vhd" -DestinationPath "C:\路径\目标文件.vhdx" -VHDType Dynamic
    +
    +# -Path:​指定原始 VHD 文件的路径。​
    +# -DestinationPath:​指定转换后 VHDX 文件的保存路径。​
    +# -VHDType:​指定磁盘类型,可选值为 Fixed(固定大小)或 Dynamic(动态扩展)。​
    +
    +

    请确保虚拟机已关闭,并且 PowerShell 以管理员权限运行。

    +
    +

    Vscode SSH 连接

    +
    +

    使用Open Remote - SSH插件,需要创建.ssh文件夹;Windows中在C://users//username//路径下。

    +

    随后使用插件新建一个连接,如:

    +
    Host myserver
    +    HostName 192.168.1.100
    +    User your_username
    +
    +
    +

    Done.

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/windows-conda-python/index.html b/public/windows-conda-python/index.html new file mode 100644 index 0000000..6e79813 --- /dev/null +++ b/public/windows-conda-python/index.html @@ -0,0 +1,438 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + +
    + + +
    + +
    + +

    乱七八糟:Windows-Jupyter开发Python

    + + + + + + +
    +

    前言 由于 Windows 中开发环境较 linux 复杂,这里总结 Windows 中使用 Jupyter 开发 Python 的环境配置。

    +

    安装

    +

    Python是一种跨平台的编程语言,社区生态丰富,有许多现成的包可以调用。传统的安装方法如下:

    +
      +
    • 下载、安装Pythond解释器;
    • +
    • 验证安装;
    • +
    • 安装VScode以及Python的拓展;
    • +
    +

    但Python开发项目时往往需要不同版本,不同的第三方包,如果用传统方法难以管理;因此现在的主流方法是:

    +
      +
    • 安装Anaconda或miniconda等Python集成包;
    • +
    • 使用conda创建并启动一个Python环境;
    • +
    • 安装jupyter编辑器编写python。
    • +
    +

    Anaconda官网下载并安装,安装成功后,命令行中敲conda info,会显示conda的版本和python的版本等详细信息;再敲conda list,会列出当前环境下所有安装的包。

    +

    安装好了Anaconda,就相当于同时有了Python、环境管理器、包管理器以及一大堆开箱即用的科学计算工具包。

    +

    使用

    +

    安装好了,默认是在base虚拟环境下,此时我们从base环境复制一份出来,在新环境里工作。

    +
      +
    • 复制base环境, 创建test环境
    • +
    +
    conda create --name test --clone base
    +
    +
      +
    • 激活test环境
    • +
    +
    conda activate test
    +
    +
      +
    • 取消Conda默认激活base虚拟环境
    • +
    +
    conda config --set auto_activate_base false
    +
    +
      +
    • 列出本机的所有环境,如下,可见当前有2个环境,当前激活的是test环境:
    • +
    +
    (test) ➜  ~ conda info -e
    +- conda environments:
    +#
    +base                     /Volumes/300g/opt/anaconda3
    +test                  *  /Volumes/300g/opt/anaconda3/envs/test
    +
    +
      +
    • Anaconda默认安装了jupyter,打开jupyter:
    • +
    +
    jupyter notebook
    +
    +

    此时会自动弹出浏览器窗口打开Jupyter Notebook网页,默认为http://localhost:8888

    +
    +

    Jupyter汉化/下载中文包:pip install jupyterlab-language-pack-zh-CN

    +
    +

    虚拟环境管理

    +
      +
    • 创建环境,后面的python=3.6是指定python的版本
    • +
    +
    conda create --name env_name python=3.6
    +
    +
      +
    • 创建包含某些包的环境(也可以加上版本信息)
    • +
    +
    conda create --name env_name python=3.7 numpy scrapy
    +
    +
      +
    • 激活某个环境
    • +
    +
    conda activate env_name
    +
    +
      +
    • 关闭某个环境
    • +
    +
    conda deactivate
    +
    +
      +
    • 复制某个环境
    • +
    +
    conda create --name new_env_name --clone old_env_name
    +
    +
      +
    • 删除某个环境
    • +
    +
    conda remove --name env_name --all
    +
    +
      +
    • 生成需要分享环境的yml文件(需要在虚拟环境中执行)
    • +
    +
    conda env export > environment.yml
    +
    +
      +
    • 别人在自己本地使用yml文件创建虚拟环境
    • +
    +
    conda env create -f environment.yml
    +
    +

    包管理

    +
      +
    • 列出当前环境下所有安装的包
    • +
    +
    conda list
    +
    +
      +
    • 列举一个指定环境下的所有包
    • +
    +
    conda list -n env_name
    +
    +
      +
    • 查询库
    • +
    +
    conda search scrapys
    +
    +
      +
    • 安装库安装时可以指定版本例如:(scrapy=1.5.0)
    • +
    +
    conda install scrapy
    +
    +
      +
    • 为指定环境安装某个包
    • +
    +
    conda install --name target_env_name package_name
    +
    +
      +
    • 更新安装的库
    • +
    +
    conda update scrapy
    +
    +
      +
    • 更新指定环境某个包
    • +
    +
    conda update -n target_env_name package_name
    +
    +
      +
    • 更新所有包
    • +
    +
    conda update --all
    +
    +
      +
    • 删除已经安装的库
    • +
    +
    conda remove scrapy
    +
    +
      +
    • 删除指定环境某个包
    • +
    +
    conda remove -n target_env_name package_name
    +
    +
      +
    • 更多命令请查看官方文档或者查询帮助命令:
    • +
    +
    conda --help
    +
    +conda install --help
    +
    +

    有了Conda包管理器,为什么Anaconda环境中,可能还需要用pip安装包呢?因为Anaconda本身只提供部分包,远没有pip提供的包多,有时conda无法安装我们需要的包,此时需要用pip将其装到conda环境里。

    +

    安装特定版本的包,conda用=,pip用==。例如:

    +
    conda install xxx=1.0.0
    +pip install xxx==1.0.0
    +
    +

    Jupyter使用

    +

    安装Anaconda并启动一个环境之后,如何让Jupyter Notebook在我们要的环境中启动呢?

    +
      +
    • 激活目标环境
    • +
    +
    conda activate myenv
    +
    +
      +
    • 安装 ipykernel(如尚未安装) +为了让 Jupyter Notebook 能识别该环境中的 Python 解释器,你需要在该环境中安装 ipykernel:
    • +
    +
    conda install ipykernel
    +
    +# 或者使用 pip
    +
    +pip install ipykernel
    +
    +
      +
    • 注册环境内核 +将该环境注册为 Jupyter 的一个内核(kernel),这样启动 Jupyter Notebook 后就能选择这个内核:
    • +
    +
    python -m ipykernel install --user --name myenv --display-name "Python (myenv)"
    +
    +# 这里 --name 指定内核的名称,--display-name 是在 Jupyter Notebook 界面中显示的名称,你可以根据需要自定义。
    +
    +
      +
    • 启动 Jupyter Notebook:依然在激活后的环境中,启动 Jupyter Notebook:
    • +
    +
    jupyter notebook
    +
    +
      +
    • 启动后,你在新建 notebook 时可以选择刚刚注册的内核 “Python (myenv)” 来确保使用该环境的 Python 解释器。
    • +
    +
    +

    当然,你也可以使用其他编辑器/IDE如 Sublime Text 或者 JetBrains 系列的 PyCharm 。

    +
    +
    +

    linux中使用Miniconda

    +
    +
    # Miniconda安装脚本
    +wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
    +# 执行以下命令启动安装程序:
    +bash Miniconda3-latest-Linux-x86_64.sh
    +# 验证安装
    +conda --version
    +
    +

    使用UV替代Conda

    +
    +

    UV(由 Astral 团队开发)是一个用 Rust 编写的高性能包管理器,提供了类似 Conda 的虚拟环境管理和依赖解析功能,并且在大多数场景下比 pip 和 Conda 快 10–100 倍。它通过命令行工具如 uv venv(创建/管理虚拟环境)和 uv pip(安装/锁定/同步依赖)来覆盖传统的 conda create、conda install、conda env export 等操作,但本身并不管理底层的 C/C++ 库,因此对于诸如 GDAL、SciPy 等需要系统级二进制依赖的包,仍建议在 Conda/系统包管理器中预装相关库,然后用 UV 来管理 Python 包。

    +
    +

    安装与激活

    +
    wget -qO- https://astral.sh/uv/install.sh | sh
    +
    +
      +
    • 在当前目录下创建 .venv,使用系统默认 Python(若不存在则自动下载)
    • +
    +
    uv venv
    +
    +
      +
    • 指定环境名称或路径
    • +
    +
    uv venv myenv
    +
    +
      +
    • 指定 Python 版本(需系统已有或可下载)
    • +
    +
    uv venv --python 3.11
    +
    +
      +
    • 激活
    • +
    +
    source .venv/bin/activate
    +
    +

    安装包

    +
    # 安装单个包
    +uv pip install requests
    +
    +# 批量安装并自动锁定依赖
    +uv pip install fastapi uvicorn sqlalchemy
    +
    +

    生成与同步锁文件

    +
    # 从 requirements.in 生成统一依赖文件
    +uv pip compile docs/requirements.in \
    +   --universal \
    +   --output-file docs/requirements.txt
    +
    +# 根据锁文件同步环境
    +uv pip sync docs/requirements.txt
    +
    +

    此流程替代 conda env export + conda env update,并保证跨平台一致性 ([GitHub][3])。

    +

    查看与卸载

    +
    uv pip list       # 列出已安装包(类似 conda list)
    +uv pip uninstall numpy
    +
    +

    替代常见 Conda 工作流

    + + + + + + + +
    Conda 操作UV 对应
    conda create -n env python=3.xuv venv --python 3.x
    conda activate envsource .venv/bin/activateactivate
    conda install pkg1 pkg2uv pip install pkg1 pkg2
    conda env export > env.ymluv pip compile requirements.in
    conda env update -f env.ymluv pip sync requirements.txt
    conda listuv pip list
    +

    最佳实践

    +
      +
    1. 系统依赖:用 Conda/Mamba 安装较难编译的 C 库(conda install gdal)。
    2. +
    3. Python 包:用 UV 管理所有纯 Python 依赖(uv pip install pandas scikit-learn)。
    4. +
    5. 统一锁定:把 uv pip compile 生成的 requirements.txt 放入版本控制,确保团队环境一致。
    6. +
    +
    +

    Done.

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/windows-iso/index.html b/public/windows-iso/index.html new file mode 100644 index 0000000..04fd60b --- /dev/null +++ b/public/windows-iso/index.html @@ -0,0 +1,251 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + +
    + + +
    + +
    + +

    乱七八糟:Windows封装与全自动安装

    + + + + + + +
    +

    前言 由于厂商默认安装windows家庭版导致各种问题频发,这里作者封装了一个开箱即用的,全自动安装,激活和优化的Windows11镜像。

    + +

    Dich-OS base on zh-cn_windows_11_business_23h2

    +

    实现了以下功能:

    +
      +
    • +绕过 Windows 11 要求检查(TPM/安全启动等)
    • +
    • +允许在没有互联网连接的情况下安装 Windows 11
    • +
    • +随机生成的计算机名称,例如:DESKTOP-ZFAH8Z2
    • +
    • +在OOBE阶段自动激活Windows(专业工作站版本)
    • +
    • +禁用 Windows 更新*
    • +
    • +删除了默认应用程序*
    • +
    • +禁用 Windows Defender
    • +
    • +在 Windows 11 中使用经典菜单,而不是二级菜单
    • +
    • +始终显示文件扩展名
    • +
    • +打开文件资源管理器到'此电脑'而不是'快速访问'
    • +
    • +任务栏中隐藏搜索框,Task view 和小部件
    • +
    • +用户密码不会过期
    • +
    • +强化 ACL
    • +
    • +禁用快速启动
    • +
    • +启用长路径
    • +
    • +启用远程桌面服务 (RDP)
    • +
    • +阻止 Windows Update 重新启动您的计算机*
    • +
    • +阻止设备 BitLocker 加密
    • +
    • +删除空 C:\Windows.old 文件夹
    • +
    • +自动将ISO中的Source$OEM$\Setup\Scripts\Files文件夹中的软件放到桌面*
    • +
    • +保留Windows 安装过程中以交互方式对磁盘进行分区
    • +
    • +保留在 Windows 安装过程中以交互方式添加本地(“脱机”)用户
    • +
    +

    PS:

    +
      +
    • +

      禁用自动更新是创建一个名为 PauseWindowsUpdate 的计划任务,一次又一次地暂停更新一周.如果要运行 Windows 更新一次,请单击 “设置”中的“恢复更新 ”.

      +
    • +
    • +

      删除默认应用程序,但保留了记事本,照片,PowerShell,Windows Terminal ,Windows Media Player (classic) ,Calculator , Clock , Xbox Apps(游戏手柄用)

      +
    • +
    • +

      这会创建一个计划任务,诱使 Windows 认为设备一直在使用中,即使更新也不会突然关机.

      +
    • +
    • +

      可以将要用的软件安装包放入该文件夹中,会自动放到桌面.

      +
    • +
    +

    感谢以下项目:

    + +

    SHA-256:5920ca1b839c2823cad5223cdff39671784d98d18da03fa4377a362ad480ce54

    +

    下载链接:这里

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/windows-some-setting/index.html b/public/windows-some-setting/index.html new file mode 100644 index 0000000..4745cb9 --- /dev/null +++ b/public/windows-some-setting/index.html @@ -0,0 +1,373 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + +
    + + +
    + +
    + +

    乱七八糟:Windows常用操作

    + + + + + + +
    +

    前言 Windows操作系统作为全球最为普及的桌面操作系统之一,其用户界面的设计非常经典,但存在许多不足之处,本篇记录一些常用脚本。

    +

    Windows11跳过联网激活 & 使用本地账号

    +

    开机之前,先断网,然后输入Shift+F10,会弹出命令行界面,并输入 +oobe\BypassNRO.cmd: +回车之后会重启,之后就可以跳过联网了,选择 +I don't have internet +即可。

    +
    +

    微软在 Windows 11 最新版中删除了 BypassNRO 脚本,以下是最新方法:

    +
    +
      +
    • +

      在 Windows 11 OOBE 登录用户账户界面按 Shift+F10 打开命令提示符 (CMD)

      +
    • +
    • +

      在命令提示符窗口中输入命令start ms-cxh:localonly按回车

      +
    • +
    • +

      此时系统将自动打开微软账户管理的窗口,在这里可以输入用户名称;在这里输入用户名和密码后继续即可,此时不再需要 BypassNRO 脚本或注册表

      +
    • +
    +

    需要注意的是目前该命令仅适用于 Windows 11 家庭版和专业版系列 (包括专业版、专业工作站版和专业教育版)。

    +

    激活windows

    +

    这里使用MAS的脚本:

    +
    irm https://get.activated.win | iex
    +
    +

    Win11关闭自动更新

    +

    1.按Win+I打开Windows设置页面。

    +

    2.单击“更新和安全”>“Windows更新”,然后在右侧详情页中选择“暂停更新7天”选项即可在此后7天内关闭Windows更新。

    +

    3.然后就可以使用脚本彻底关闭更新:将以下命令保存为.bat文件,运行即可。

    +
    ::Windows auomatic updates
    +reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU /v AutoInstallMinorUpdates /t REG_DWORD /d 1 /f
    +reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU /v NoAutoUpdate /t REG_DWORD /d 1 /f
    +reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU /v AUOptions /t REG_DWORD /d 4 /f
    +reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v AUOptions /t REG_DWORD /d 4 /f
    +reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate /v DisableWindowsUpdateAccess /t REG_DWORD /d 0 /f
    +reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate /v ElevateNonAdmins /t REG_DWORD /d 0 /f
    +reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer /v NoWindowsUpdate /t REG_DWORD /d 1 /f
    +reg add "HKLM\SYSTEM\Internet Communication Management\Internet Communication" /v DisableWindowsUpdateAccess /t REG_DWORD /d 0 /f
    +reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\WindowsUpdate /v DisableWindowsUpdateAccess /t REG_DWORD /d 0 /f
    +sc stop wuauserv
    +sc config wuauserv start=disabled
    +sc stop WaaSMedicSvc
    +sc config WaaSMedicSvc start=disabled
    +reg add HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\InstallService\State /v AutoUpdateLastSuccessTime /t REG_SZ /d "2100-01-01T00:00:00+08:00" /f
    +reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings /v PauseFeatureUpdatesStartTime /t REG_SZ /d "2100-01-01T00:00:00Z" /f
    +reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings /v PauseQualityUpdatesStartTime /t REG_SZ /d "2100-01-01T00:00:00Z" /f
    +reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings /v PauseUpdatesExpiryTime /t REG_SZ /d "2100-01-01T00:00:00Z" /f
    +reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings /v PauseFeatureUpdatesEndTime /t REG_SZ /d "2100-01-01T00:00:00Z" /f
    +reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings /v PauseQualityUpdatesEndTime /t REG_SZ /d "2100-01-01T00:00:00Z" /f
    +
    +

    如果要恢复更新,使用以下命令,同样保存为.bat运行:

    +
    ::Windows auomatic updates
    +reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU /v AutoInstallMinorUpdates /t REG_DWORD /d 0 /f
    +reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU /v NoAutoUpdate /t REG_DWORD /d 0 /f
    +reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU /v AUOptions /t REG_DWORD /d 0 /f
    +reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v AUOptions /t REG_DWORD /d 4 /f
    +reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate /v DisableWindowsUpdateAccess /t REG_DWORD /d 1 /f
    +reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate /v ElevateNonAdmins /t REG_DWORD /d 1 /f
    +reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer /v NoWindowsUpdate /t REG_DWORD /d 0 /f
    +reg add "HKLM\SYSTEM\Internet Communication Management\Internet Communication" /v DisableWindowsUpdateAccess /t REG_DWORD /d 1 /f
    +reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\WindowsUpdate /v DisableWindowsUpdateAccess /t REG_DWORD /d 1 /f
    +sc config wuauserv start=auto
    +sc start wuauserv
    +sc config WaaSMedicSvc start=auto
    +sc start WaaSMedicSvc
    +reg add HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\InstallService\State /v AutoUpdateLastSuccessTime /t REG_SZ /d "2000-01-01T00:00:00+08:00" /f
    +reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings /v PauseFeatureUpdatesStartTime /t REG_SZ /d "2000-01-01T00:00:00Z" /f
    +reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings /v PauseQualityUpdatesStartTime /t REG_SZ /d "2000-01-01T00:00:00Z" /f
    +reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings /v PauseUpdatesExpiryTime /t REG_SZ /d "2000-01-01T00:00:00Z" /f
    +reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings /v PauseFeatureUpdatesEndTime /t REG_SZ /d "2000-01-01T00:00:00Z" /f
    +reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings /v PauseQualityUpdatesEndTime /t REG_SZ /d "2000-01-01T00:00:00Z" /f
    +pause
    +
    +

    使用CMD恢复完整右键菜单

    +

    Win11的显示更多选项的二级菜单过于繁琐,怎么设置才能将其关闭,并恢复成Win10的状态呢?

    +

    步骤1.Win+S打开搜索框,输入cmd并以管理员身份运行命令提示符。

    +

    步骤2. 输入以下命令并按Enter键执行。

    +
    reg add HKCU\Software\Classes\CLSID{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32 /ve /d “” /f
    +
    +

    或者

    +
    reg add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve
    +taskkill /f /im explorer.exe 
    +start explorer.exe
    +
    +

    如果想要重新打开Win11新样式的右键菜单的话,以同样的方式在命令提示符中执行此命令:

    +
    reg delete "HKCU\Software\Classes\CLSID{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}" /f
    +
    +

    Win11关闭 Windows Defender

    +

    Windows Defender具有防篡改保护,因此需要先在设置-安全中心-设备保护中将实时防护关闭,然后在组策略或者注册表中将其禁用。

    +
      +
    • 使用Windows + R快捷键打开「运行」对话框,执行regedit打开注册表编辑器。
    • +
    • 导航至以下路径:
    • +
    +
    HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender
    +
    +
      +
    • 将名为DisableAntiSpyware的 DWORD (32位) 值设置为1,如果没有就新建。
    • +
    • 重启后生效。
    • +
    +

    Win11添加开机自启动项方法

    +

    选择“开始”按钮 ,然后滚动查找你希望在启动时运行的应用。

    +

    右键单击该应用,选择“更多”,然后选择“打开文件位置”。此操作会打开保存应用快捷方式的位置。如果没有“打开文件位置”选项,这意味着该应用无法在启动时运行。

    +

    文件位置打开后,按win+ R,键入“shell:startup”然后选择“确定”。这将打开“启动”文件夹。

    +

    将该应用的快捷方式从文件位置复制并粘贴到“启动”文件夹中,即添加启动项成功。

    +

    Windows 指定时间服务器&&使用UTC

    +

    右键点击任务栏上的时间,选择 "调整日期/时间"。在日期和时间窗口中,点击互联网时间标签。点击 "更改设置…" 按钮。在弹出的对话框中,勾选同步时钟与 Internet 时间服务器,然后在 "服务器" 输入框中填写你想要的时间服务器,例如:

    +
    time.windows.com(微软默认服务器)
    +time.nist.gov(美国国家标准技术研究院的时间服务器)
    +pool.ntp.org(一个公共的 NTP 时间服务器池)
    +
    +

    应用更改:点击 "更新现在",然后 "确定" 保存设置。

    +
      +
    • 如果有linux/win双系统,可以让 Windows 使用 UTC 作为硬件时钟时间:
    • +
    +
    # 在 Windows 中以管理员权限运行命令提示符,执行:
    +reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /t REG_DWORD /d 1 /f
    +
    +

    调整网络优先级

    +
      +
    • 查看当前优先级(PowerShell/管理员)
    • +
    +
    Get-NetIPInterface
    +
    +

    你会看到类似:

    +
    IfIndex  InterfaceMetric   InterfaceAlias
    +-------  --------------   --------------
    +15       25              Wi-Fi
    +3        15              以太网
    +
    +# InterfaceMetric 值越小,优先级越高。
    +
    +
      +
    • 修改网络优先级
    • +
    +

    将有线网络(以太网) 设为更高优先级(值更小):

    +
    Set-NetIPInterface -InterfaceIndex 3 -InterfaceMetric 10
    +
    +
      +
    • 将 WiFi 设为更低优先级:
    • +
    +
    Set-NetIPInterface -InterfaceIndex 15 -InterfaceMetric 25
    +
    +
      +
    • 重启网络
    • +
    +
    Restart-NetAdapter -Name "以太网"
    +
    +

    这样,当网线插入时,Windows 会优先使用有线网络;断开网线后,自动切换到 WiFi。

    +
      +
    • 如需永久设置,可修改注册表:
    • +
    +

    Win + R 输入 regedit 打开注册表编辑器,进入路径:

    +
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces
    +
    +

    在 Interfaces 里找到你的有线网卡和无线网卡(可以根据 IP 或 MAC 地址确认)。

    +
      +
    • 创建/修改 Metric 值:
    • +
    +
    有线网卡(Ethernet):设为 10
    +无线网卡(WiFi):设为 25
    +
    +

    重启电脑生效。

    +

    清理代理

    +
    +

    保存为.bat格式

    +
    +
    @echo off
    +REM 清理代理设置
    +REG DELETE "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable /f
    +REG DELETE "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer /f
    +echo 代理设置已清除
    +
    +

    开/关3D加速

    +
    +

    保存为.reg格式

    +
    +

    开启3D加速

    +
    Windows Registry Editor Version 5.00
    +[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectDraw]
    +"EmulationOnly"=dword:00000000
    +[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Direct3D\Drivers]
    +"SoftwareOnly"=dword:00000000
    +[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\DirectDraw]
    +"EmulationOnly"=dword:00000000
    +[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Direct3D\Drivers]
    +"SoftwareOnly"=dword:00000000
    +
    +

    关闭3D加速

    +
    Windows Registry Editor Version 5.00
    +[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectDraw]
    +"EmulationOnly"=dword:00000001
    +[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Direct3D\Drivers]
    +"SoftwareOnly"=dword:00000001
    +[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\DirectDraw]
    +"EmulationOnly"=dword:00000001
    +[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Direct3D\Drivers]
    +"SoftwareOnly"=dword:00000001
    +
    +
    +

    Done.

    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + + + diff --git a/public/windows-vscode-gcc/index.html b/public/windows-vscode-gcc/index.html new file mode 100644 index 0000000..a7776b3 --- /dev/null +++ b/public/windows-vscode-gcc/index.html @@ -0,0 +1,241 @@ + + + + + Dich'blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + +
    + + +
    + +
    + +

    乱七八糟:Windows-VScode开发C/C++

    + + + + + + +
    +

    前言 由于 Windows 中开发环境较 linux 复杂,这里总结 Windows 中使用 VScode 开发 C/C++ 的环境配置。

    +

    步骤

    +
      +
    • 下载安装 Vscode(Visual Studio Code)
    • +
    • 配置安装中文插件,C/C++插件和 Code Runner 插件
    • +
    • 安装 MinGW64 编译器并配置环境变量
    • +
    • 配置 tasks.json 和 launch.json
    • +
    • 开始C/C++之旅!
    • +
    +

    安装VScode

    +
      +
    • 官网-微软官方版
    • +
    • vscodium-社区开源版本,去除官方版中不开源成分
    • +
    +

    配置插件

    +
      +
    • 默认为英文,在左侧 Extensions 中安装 Chinese(simplified) 插件,重启即可变为中文;
    • +
    • 随后安装C/C++插件,即下载名称为cpptools-windows-x64.vsix +的插件并在扩展中从VSIX安装,然后搜索 Code Runner 并安装。
    • +
    +

    安装 MinGW64 编译器

    +
      +
    • +

      首先打开官方文档,然后点击左侧的 Downloads,再点击 Pre-built Toolchains。往下拉,可以看到许多系统的下载包,这里我们选MinGW-W64-builds并点击。页面自动跳转,再点击最上方的 MinGW-W64-builds 下的 GitHub 链接。

      +
    • +
    • +

      进入Github,找到x86_64-14.2.0-release-win32-seh-ucrt-rt_v12-rev1.7z(版本会更新,选择最新的即可)点击然后下载。

      +
    • +
    • +

      下载完成后解压得到 mingw64 文件夹,将其移动到C:\Program Files下,随后复制该文件夹中/bin的路径。

      +
    • +
    • +

      按下 Win + S,在搜索框中输入“系统环境变量”,点击“编辑系统环境变量“,点击环境变量。在下方的系统变量中,选中Path,然后点击编辑,点击右侧的新建,然后黏贴刚刚拷贝的路径,随后一直用确定退出。

      +
    • +
    • +

      检验是否成功:在cmd中输入gcc -v,如果有版本号则成功。

      +
    • +
    +

    配置JSON

    +
      +
    • 回到 Visual Studio Code 继续配置。点击左侧的资源管理器,点击打开文件夹,创建一个.cpp文件,里面代码可以是
    • +
    +
    #include <iostream>
    +
    +int main() {
    +    std::cout << "Hello" << std::endl;
    +    return 0;
    +}
    +
    +
      +
    • +

      保存,然后点击右上角的三角形,选择“运行C/C++文件”。此时上方的搜索框会有弹出,点击“C/C++: g++.exe 构建和调试活动文件”。 然后会生成一个 .vscode 的文件夹,里面包含 tasks.json 文件。打开这个文件,然后按需调整,设置栈空间(这里设置成了256MB)和 C++ 标准(这里设置成C++17)。

      +
    • +
    • +

      接着生成调试文件,用于进行 debug。点击左侧的运行和调试,然后点击“创建 launch.json 文件”。点击弹出的“另外 C++ (GDB/LLDB) 个选项”。

      +
    • +
    • +

      点击右下角的“添加配置”,然后点击“C/C++: (gbd) 启动”。对Program部分进行修改(编译产物的路径)。

      +
    • +
    +
    +

    手动编译:g++ <源代码的相对路径> 手动运行编译产物:一般为./a.out

    +
    +

    至此 Visual Studio Code 的 C++ 环境已经配置完成。

    +
    +

    在ubuntu上配置环境需要安装 sudo apt install build-essential gdb cmake clangd clang-format libstdc++-dev

    +
    +
    +

    Done.

    + +
    + + + + +
    + +
    + + + + +
    + + +