使用WSL创建精简的Hexo写作环境

这篇文章将介绍一种方法,使用Windows Subsystem for Linux (WSL), Alpine Linux发行版, Git等工具,配置一个方便易用的的Hexo博客编写系统。

如果结合已有的网站服务器,还可以使用Git快速进行站点部署与更新。

前言

我曾经在19年尝试过使用Hexo作我的博客生成器。众所周知,Hexo是跑在Node.js上的玩意,但npm环境配置是出了名的复杂,甚至在我看来还不是那么优雅,特别是在Windows平台上。

所以,当我再次选择Hexo作博客生成系统的时候,我就在想,是否有一种方法,在整体性能良好的前提下,可以方便地进行Hexo环境的隔离管理,又在Windows下面有较好的博客编写体验呢?

现在是2021年的年底,我认为微软的WSL是解决这一问题的,比较优雅的方法。接下来就让我们看看怎么做吧。

预备条件

  • 启用了 Windows Subsystem for Linux 功能的 Windows 10+ 操作系统
  • Alpine Linux的MINI ROOT FILESYSTEM(最小根文件系统)压缩包,可以在downloads | Alpine Linux找到
  • 其他所需工具,如Git等

关于Alpine Linux

Alpine Linux是一个非常精简的Linux发行版,本文编写时,其最新版minirootfstar.gz包,仅2.6MB大小,可以在为我们提供尽可能的环境隔离同时,大幅度节省隔离环境所需的额外空间开销。

MINI ROOT FILESYSTEM的作用是?

用于我们手动导入Alpine Linux到WSL中,作为我们的Hexo环境。不过,目前微软商店里已经上架了Alpine WSL应用程序包,和手动导入效果类似,可供选择。如果选择从应用商店安装,请跳过下面导入Alpine Linux一节。

为什么使用Alpine Linux发行版?

Alpine Linux发行版体积比目前绝大多数其他通用的发行版(无论是Debian系还是CentOS系)都要小得多。先前,Alpine由于musl的原因,兼容性不如其他glibc发行版。但后来docker普及之后,许多软件都提供了运行于Alpine Linux的二进制文件。包括Visual Studio Code远程插件,也提供了Alpine Linux的支持。因此,就本文描述的任务而言,选用Alpine Linux是完全没有问题的。

当然,如果更喜欢使用其他发行版,也是完全没有问题的,操作流程和下文整体上还是相同的。注意一下部分命令的替换就好。

导入Alpine Linux

解开GZip包

这一步,我们要导入Alpine Linux系统作为一个WSL的发行版(Distro)。

首先下载Alpine Linux的.tar.gz包,然后用解压工具,解压出.tar包。记住/复制这个.tar包的路径。例如,D:\alpine-minirootfs-3.15.0-x86_64.tar

注意事项

只需要将压缩包的第一层.gz部分解开,得到里面的.tar包即可。不需要解开.tar包里面的文件系统。

建立目录并导入发行版

在你希望放置这个发行版相关系统文件的地方,创建一个文件夹,这里为了举例子,我们取D:\AlpineHexoBlog。这个路径不一定需要在C盘,可以在你想的合理的位置。名字也是随意的。

接着,我们输入下述命令。

1
wsl --import AlpineHexo D:\AlpineHexoBlog D:\alpine-minirootfs-3.15.0-x86_64.tar --version 2

这个命令的意思是,将我们解压得到的.tar包,作为一个Linux发行版,导入一个新的发行版,并将相关文件放置在D:\AlpineHexoBlog目录下,这个发行版的名称叫AlpineHexo(这个名字可以随意),并指定使用WSL版本2(关于WSL1和2的差别,请自行参阅微软官方文档)。

这样,一个自定义的发行版就导入完成了。可以在普通命令行/Powershell里面输入wsl -d AlpineHexo(注意名称替换)进入该发行版的终端。如果电脑装有Windows Terminal,也可以在标签页启动列表中直接选择该发行版。

安装Hexo相关环境

切换到Alpine Linux终端,执行命令。

1
apk add nodejs npm git

等待安装完成。

安装Hexo

这部分的步骤和Hexo官方文档部分相同。这里就直接给命令了。

1
npm install -g hexo-cli

创建博客资源主目录

参考Setup | Hexo

1
hexo init MyBlog

这里的MyBlog是你指定的一个文件夹名称,这个文件夹将存储和这个Hexo站点相关的绝大部分文件。接下来的内容中,我会将这个目录称为Hexo主文件夹

如果输出如下所示,说明创建成功了。

1
2
3
INFO  Cloning hexo-starter https://github.com/hexojs/hexo-starter.git
INFO Install dependencies
INFO Start blogging with Hexo!

接着进入这个新文件夹,然后执行npm install

1
2
cd MyBlog
npm install

这下,我们的站点就初始化完成了。接下来,你就可以任意对这个站点进行想要的自定义,如主题自定义,编写页面和文章等。


(可选)使用Git管理站点内容历史记录

然而,上面这些内容,是不足以让我写一篇文章的。因此,我们会多介绍一些内容。

我们首先从使用Git管理站点内容历史记录开始说起。网站的内容日新月异,因此有一定的需要,将我们的博客站点原始内容,如博客文章的原始Markdown文件,站点的配置文件,Node.js包依赖等,做一些历史备份。Git就是我们执行这项任务的极佳选择。

我们的内容不依赖于具体的Git云托管平台实现,不必纠结Github还是Gitee这种问题。方法都是通用的。

初始化Git仓库

进入Hexo主文件夹,并执行git init。这将在我们本地端创建一个初始Git仓库。

1
2
cd MyBlog
git init

接着,我们让git跟踪Hexo主文件夹内的,有用的文件,并进行第一次提交(commit)。其中-m参数后的是提交信息,内容任你填写。

1
2
git add .
git commit -m "Init Push"

推送到在线Git云托管平台

如果希望同步到在线的Git云托管平台,需要先自行在网页中创建一个空仓库,之后推送到该远程仓库中。这里以内网的一台Git服务器为例,创建的仓库地址为http://git.mysrv.in/dhao2001/MyBlog.git

1
2
git remote add origin http://git.mysrv.in/dhao2001/MyBlog.git
git push -u origin main

在另一个地方继续创作

下次,当你重装了操作系统,或是更换了电脑,希望在另一个地方恢复相同的博客环境以及源文件,可以这么做:

首先还是要搭好最基本的环境,也就是git, nodejs, npm。安装完成后克隆仓库到当前系统。

1
git clone http://git.mysrv.in/dhao2001/MyBlog.git

进入该文件夹,执行npm install,等待包安装完成,环境配置就完成了。

1
2
cd MyBlog
npm install

接下来,就像在老地方一样创作和发布。


(可选)使用Git进行页面部署

咦,怎么又是Git?上一节不是刚刚才讲过吗?

  • 上一节主要是使用Git对博客的原始配置文件、原始代码、原始Markdown源文件进行管理。
  • 而本节的内容是使用Git,将本机上使用Hexo命令渲染生成的静态Html等站点资源文件,推送到远程服务器的指定Web目录内,供其他人通过Web服务器进行访问。

设置远程服务器

我们第一步,首先请登录到我们的目标主机,也就是我们部署在公网的Web服务器上。

接着,按照服务器上运行发行版的方法,安装git, nginx这两个软件包。例如,在Debian/Ubuntu系统上运行:

1
sudo apt install git nginx-full

在其他发行版上请自行调整相关命令。

关于Web服务器的选择

这里我们使用了Nginx作为我们的Web服务器。如果使用了其他Web服务器如Apache,请自行调整下面步骤中关于Web服务器配置文件的内容。

设置Web服务器

我们在/var/www下新建一个文件夹,用于存放我们网站的静态Html文件。我们可以选择新建一个名为blog的文件夹用于此用途。

1
2
cd /var/www/
mkdir blog

接下来修改nginx的站点配置文件(Debian/Ubuntu系统位于/etc/nginx/sites-available/下),修改当前server(新建一个也无妨,注意server_name属性等不要冲突即可)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 80 default_server;
listen [::]:80 default_server;

root /var/www/blog;

index index.html;

server_name _;

location / {
try_files $uri $uri/ =404;
}
}

修改完配置文件后,重启nginx:

1
2
3
4
5
service nginx restart   # 使用系统服务管理重启nginx

# 如果上面的命令无效
# If the command above doesn't work
nginx -s reload # 使用nginx自身命令重新读取配置文件

完成上述设置后,Web服务器配置就基本完成了,这些配置项目对Hexo这样的静态网站来说足够了(SSH啥的请自行设置)。如果心里没底的话,可以在/var/www/blog/下面,新建一个index.html,随便写点什么,保存。然后打开浏览器,访问目标服务器,看能不能正常访问即可。

设置git仓库用于传输博客文件

Web服务器部分设置结束后,接下来的问题就是,我们怎么将我们在本机上生成的Hexo站点静态文件,推送到远程Web服务器上的对应目录,在本例中,也就是/var/www/blog中去呢?

我们解决这个问题的步骤分成两步。

  • 第一步,先将本机生成的静态文件,通过Git传输到Web服务器上。
  • 第二步,将传输到Web服务器上的文件,复制到/var/www/blog

相关的配置需要在本机和远程Web服务器上配合完成。

远程Web服务器的配置

首先,在远程Web服务器上,创建git用户。

1
adduser -s /bin/git-shell git

关于Git Shell

出于安全考虑,我们将git用户的默认shell指定为只有简单功能的git-shell,执行命令结束后就会退出。/bin/git-shell是Debian/Ubuntu系发行版的默认路径,新版本或其他发行版请务必确认git-shell的具体位置,并将/bin/git-shell替换成该真实路径。

为了配置自动部署,我们建议使用公钥进行认证。

1
2
3
4
5
6
cd /home/git
su git -s /bin/bash # 以git用户身份进行下列操作
mkdir .ssh
cd .ssh
vim authorized_keys # 将公钥添加到authorized_keys中
chmod 600 authorized_keys # 这步很重要,权限不对可能导致git用户无法通过SSH登录

完成用户创建后,我们选择一处地方,创建一个git裸仓库,用于在后续步骤中我们上传生成的静态页面文件。git用户的家目录/home/git似乎是一个不错的选择。

1
2
cd /home/git/
git init --bare myblog.git

为了在上传页面文件后,系统自动将更新的页面文件同步到/var/www/blog文件夹,我们创建一个post-receive钩子。

1
vim myblog.git/hooks/post-receive

添加如下内容。

1
2
#!/bin/sh
git --work-tree=/var/www/blog --git-dir=/home/git/myblog.git checkout -f

保存该文件,回到终端,赋予该文件可执行权限。

1
chmod 744 myblog.git/hooks/post-receive

最后,将这个仓库文件夹的所有权移交到git用户手上。

1
chown -R git:git myblog.git/

也不要忘记将nginx网站根目录/var/www/blog所有权转移给git,否则将无法进行写入和更新操作!

1
chown -R git:git /var/www/blog

这样,远程Web服务器端的配置就完成了。

本机端的操作

这部分的配置参考One-Command Deployment | Hexo

回到本机上的WSL Hexo环境。首先还是切到Hexo主文件夹。

1
cd MyBlog

为了使用Git进行一键部署,我们需要安装Hexo的Git一键部署插件。

1
npm install hexo-deployer-git --save

_config.yml最后deploy下添加一节。

_config.yml
1
2
3
4
5
deploy:
- type: git
repo: git@mysrv.in:myblog.git
branch: master
message:

记得把mysrv.in替换成你的远程Web服务器地址。如果有其他需求,如指定认证使用的私钥位置、端口等,可以参考我先前写的文章SSH配置主机别名及指定认证私钥路径,修改ssh_config文件实现。

完成以后,试试运行命令:

1
hexo g -d

然后再访问一下博客站点,是不是已经成功将Hexo内容部署上去了呢?


常见问题的解决

本机部署命令执行成功,但远程服务器上访问到的资源未更新

首先,重新加载资源最好通过Ctrl+F5快捷键强制刷新以避免缓存对调试结果造成影响。

其次,检查网站目录/var/www/blog的内容是否已经更新。如果里面的文件是更新了的,有效的Hexo站点文件,请检查nginx配置文件。

如果明明git推送成功,但却没更新到网站目录中,需要检查post-receive钩子内容是否正确,路径是否正确,权限是否正确。正确的权限是,权限8进制代码为744755,所有者为git:git。可以通过下列命令指定。

1
2
chmod 744 post-receive
chown git:git post-receive

修改博客后更新资源时,字母大小写异常

这是由于默认的Hexo Git插件对大小写不敏感导致的。需要修改<Hexo主目录>/.deploy_git/.git/下面的config文件,在[core]一节中添加一行ignorecase = false:

1
2
3
4
5
6
7
8
9
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = false
[branch "master"]
remote = git@mysrv.in:myblog.git
merge = refs/heads/master