与 Hexo 配合使用 Sass 和 Webpack

为何使用 Sass 和 Webpack Sass 是 CSS 的超集,在 CSS 的基础上扩展了大量的语法,支持规则嵌套、变量定义、include 等功能,也可以进行数学运算。主要功能可以在 官方入门教程 中查看。Sass 原先的文件格式扩展名是 sass,其结构类似 yaml,似乎不与传统 CSS 兼容;而目前 Sass 的文件格式是 scss,兼容 CSS 文件。 我使用 Sass 的目的,一是更加清晰的 CSS 规则管理。例如,我有一些 CSS 规则希望只对网站顶栏生效,我就可以将它们全部放到一个代码块中方便管理: header { h1 { ... } } 二是减少网页加载时的 CSS 代码量。虽然我的网站使用了 Bootstrap,但是我只使用了一小部分功能,即 Bootstrap 的栅格系统,导航栏和下拉菜单,其它大部分功能都没有使用,这部分 CSS 就不必加载。同时,我还通过 CSS !important 覆盖的方式对一些 Bootstrap 的颜色、形状进行了自定义,这也引入了额外的代码量。 我在我的 scss 文件中定义了全局的控件颜色、字体大小等,...

开始使用 Hexo 静态网站生成器

什么是静态网站生成器 我们常用的 WordPress、Typecho 等 CMS(内容管理系统)都是动态网站。当用户访问网页时,服务端运行使用 PHP、Python、Node.js 等语言的程序,根据用户的请求 实时 产生网页,将其返回给用户。 而 Jekyll、Hexo、Hugo 等静态网站生成器采取的是另一种方法: 提前 预测用户的请求,一次性产生对应的 HTML 文件。 这两种方式的主要优缺点如下: 谁更占优 动态网站 静态网站 动 可以实现复杂的交互,根据用户的输入随时改变内容 只能响应预定的输入,灵活性差 动 大多数 CMS 都会提供易用的管理后台,方便用户随时更新内容 没有在线后台,需要在本地安装额外软件更新网站内容 静 安装脚本运行环境需要较复杂的配置 服务端无需脚本运行环境,几乎无需服务端任何配置 静 实时产生网页需要较大的运算量(包括脚本运行、数据库查询),对服务器造成较大的压力 服务端几乎无需计算,响应速度极快 静 如果需要迁移服务器,...

(自建 NTP)在 Tinker Board 上使用 PPS 的插图

(自建 NTP)在 Tinker Board 上使用 PPS

在 前一篇文章 中,我使用 Tinker Board 和 ATGM336H GPS/北斗模块自建了 NTP 服务器,以 GPS 作为时间基准。GPS 模块除了提供传统的串口输出 NMEA 语句之外,还额外提供了一个 PPS 信号,这个信号会每秒变化一次。原本 gpsd 需要不断解析 GPS 模块传来的 NMEA 语句,需要耗费不短的时间,并且容易被其它程序抢占运行时间,产生 delay(延迟)和 jitter(波动)。而 PPS 信号可以直接触发 CPU 的中断,运行一个简单的处理程序,让操作系统以高优先级处理,不会被其它程序影响。 一般而言,在 Linux 中,PPS 由内核直接提供驱动支持。但是在前文中,由于 Tinker Board 的 Armbian Linux 内核没有提供 PPS 支持,所以我们没法直接开启。 解决方法 1:重新编译内核 如果内核没有对应支持,那就重新编译内核,加上功能就好。 Tinker Board 论坛上的这篇帖子 中提供了一个内核补丁,为内核加上了 PPS 支持。打上补丁、编译内核后,将 PPS 信号连到第 22 针,...

自建基于 GPS 的 NTP 服务端 的插图

自建基于 GPS 的 NTP 服务端

NTP 是什么 NTP(Network Time Protocol)是目前使用最广泛的互联网时间同步协议。我们常用的 Windows、macOS、Linux 等都自带了 NTP 客户端,可以连接远程服务器获取当前的时间。例如,Windows 的 Internet 时间同步功能就是基于 NTP: (图片来自网络) Windows 默认会连接到 time.windows.com 这台由微软维护的 NTP 服务器同步时间。但是,默认的这台服务器在国内并不好用。这台服务器位于美国,到国内的延迟很大并且容易波动,因此 NTP 客户端也很难得出准确的时间。 那么中国大陆有没有 NTP 服务器呢?有,但是不多: cn.pool.ntp.org 由 www.pool.ntp.org 维护的 NTP 服务器池项目,所有服务器由志愿者提供,在各个地区通过 DNS 负载均衡到不同的服务器上。 现在(2019 年 9 月 16 日)共有 63 台服务器位于 CN 池内(但不是所有的服务器都在国内) 可以通过 0.cn.pool.ntp.org,1.cn.pool.ntp.org 等方式获得更多的服务器 cn.ntp.org....

使用 GPP 预处理 Dockerfile,实现 #include、#if 等功能

由于我有多种架构的设备运行 Docker(包括 x86_64 的电脑和服务器,ARM32v7 的 Tinker Board 和 ARM64v8 的树莓派 3B),我的每个 Docker 镜像都要构建多种版本。最初我 给每个架构单独写一份 Dockerfile ,但是很明显这样难以统一管理,在软件更新修改 Dockerfile 时经常漏改文件。之后,我用的是 Docker 的构建参数功能 ,即 --build-arg 参数,根据参数来调用不同的基础镜像、下载不同文件。 但是这样还是有很大的局限性。首先,不同项目对不同架构的称呼是不一样的。例如,我们平时说的 x86 32 位架构,i386,就被 Go 以及众多使用 Go 的项目叫做 386。类似的,ARM32v7 也可以叫做 ARMHF,而 ARM64v8 有三种写法(ARM64v8,ARM64,AARCH64)。之前,我就不得不用 bash 脚本转换出不同的称呼组合在不同的地方使用,但是这样做就需要设置很多的变量,非常麻烦。 另外,有些镜像在特定架构下需要特殊处理。例如,...

在 DN42 中使用 Docker 建立 Anycast DNS 服务

2020-03-16 提示 本文中的方案已有更新版本:参见《 Docker 容器共享网络命名空间,集成 Bird 实现 Anycast 高可用 》。 建议阅读本文的概念介绍部分及 Bird 的大致配置,配合上文的 Docker 部署方案使用。 什么是 Anycast 互联网上常用的路由协议 BGP 是这样工作的: 我在 DN42 拥有 IP 段 172.22.76.104/29。 我通过 BIRD 等 BGP 软件,「宣告」这台服务器上可以访问到 172.22.76.104/29 这个 IP 段。 与我有 Peering 的其它服务器记录下这一条消息:「通过某条路径,走 1 格可以访问到 172.22.76.104/29。」 其它服务器向与它们有 Peering 的服务器继续宣告:「这台服务器距离 172.22.76.104/29 只有 1 格距离。」 以此类推,其余服务器也通过类似的流程,宣布自己与 172.22.76.104/29 有 2 格,3 格,4 格距离…… 所有服务器也都通过距离最短的路径,将数据发送到我的服务器。 在这种情况中,只有一台服务器宣布自己是 172.22.76.104/29 的「源头」。...

Typecho 主题性能优化和缓存

为了实现 Lightbox、代码高亮等功能,我在我的博客主题中写了一些后处理代码,对 Typecho Markdown 输出后的 HTML 代码再进行一层处理。但是因为我的博客历史文章较多,我在不同时期也用了不同的编辑器(WordPress 编辑器,百度 UEditor 等等),为了尽可能保证历史文章也能正常显示,我的处理逻辑比较复杂。再加上我用的廉价 VPS 性能本就不怎么样,相应的网页加载时间也较长。 我在 nginx 配置中添加了这样一行,以在 HTTP 头中输出网页在服务器端处理的用时: add_header LT-Latency $request_time ; 最初,这个值是 0.25 左右,代表着每个网页需要在服务器端处理 250ms 之久。于是,我在大概一年前( 2018 年 3 月 11 日,《大幅优化了博客主题性能》 )大改了一轮后处理逻辑,修改点大致如下: 原先,为了对应历史文章代码,我使用多条正则表达式一条条进行匹配、替换。我在修改时将有些正则表达式整合成一条,...

Go 语言实现的 Bird-lg(Bird Looking Glass) 的插图

Go 语言实现的 Bird-lg(Bird Looking Glass)

什么是 BIRD?什么是 Bird-lg? BIRD 是 Linux 上常用的一款 BGP 路由软件。我主要 在 DN42 网络内使用 Bird ,与其它用户建立连接。 Bird-lg 是 GitHub 用户 sileht 开发的一款基于 Python 2 的程序。它提供了一个网页面板,可以显示各个服务器上的 BIRD 路由软件的状态,以及查询到指定 IP 的路由。 为什么我要用 Go 语言重写? Bird-lg 基于 Python 2 以及 Flask,因此占用内存较大(20-30 MB)。 Bird-lgproxy 内存占用量也差不多 20 MB,并且每台服务器上都要运行一个。本站所在的 512 MB 内存的 VPS 已经出现过多次由于内存耗尽外加 SWAP 所在硬盘读写缓慢,导致 Docker、nginx、MySQL、PHP 轮流崩的情况,只能重启解决。 Go 重写版本只消耗 6 MB 内存。 Bird-lg 读取多个服务器的状态是 按顺序 进行的,而非并行进行。有时某台服务器网络状态不好,或者 ZeroTier One 抽风,会导致读取时卡较长时间。 Go 重写版本使用 Goroutine 并行 请求多台服务器,...

BuyPass GO SSL 证书试用 的插图

BuyPass GO SSL 证书试用

BuyPass 是挪威的一家 CA,提供数字证书、安全认证产品等多种服务。最近 BuyPass 上线了基于 ACME 的自动签发证书服务,类似于 Let's Encrypt,这项服务称为 BuyPass GO。与 Let's Encrypt 主要的不同点在于他们的证书每次签发有效期是 180 天,比 Let's Encrypt 的长一倍。所以如果你需要给你的服务手动换证书,BuyPass 的证书会好一些。另外 BuyPass 暂不支持签发泛域名证书(俗称野卡?),只能将需要的域名一个个列出来。 (不过我觉得如果需要手动换证书,还是申请 TrustAsia 之类的一年有效期的好一点) 申请证书 我使用 acme.sh 这个工具来申请证书。第一步是注册用户。与 Let's Encrypt 不同,BuyPass 要求在注册时提供一个有效的邮箱: cd /root/.acme.sh ./acme.sh --server https://api.buypass.com/acme/directory --register-account --accountemail [你的邮件地址] 如果你的域名有 CAA 记录,限制哪些 CA 能签发证书,...

使用 Docker 构建参数,多架构共享一份 Dockerfile 的插图

使用 Docker 构建参数,多架构共享一份 Dockerfile

由于我有多种架构的设备运行 Docker(包括 x86 服务器,树莓派,Tinker Board),对于每个常用的软件,我 需要为每种不同架构都构建一份镜像 。之前,我采用的方式是每个架构都有一个独立的 Dockerfile, 类似于这样 : 可以看到每份 Dockerfile 除了 FROM 调用的镜像不一样,其它几乎完全相同。用这种方式管理,好处是写构建脚本(travis.yml)的时候简单,直接一个个 docker build 过去即可,但是坏处也很明显,每次软件有版本更新,或者我决定添加或删除一个功能,我都要改好几份 Dockerfile。 前两天我查资料时,发现了 Docker 的一个功能:构建参数(Build args),就是可以填入一些参数供构建过程使用。于是我就决定修改构建脚本,将不同架构的 Dockerfile 合并。 使用构建参数 Dockerfile 中使用 ARG 命令就可以定义一个构建参数,它可以像 ENV 定义出的环境变量一样使用: # 定义一个名为 THIS_ARCH 的参数 ARG THIS_ARCH # 或者给它定义上默认值:...