02_将博客推送到服务器上

总结摘要
本篇实现博客推送到服务器中。具体步骤如下:首先在服务器上安装 Git、Hugo 和 rsync 软件。其次,在服务器中创建博客仓库和静态资源文件夹。再次,通过 rsync 同步本地和服务器的静态图片资源,采用 Git 同步博客仓库。最后,用 Hugo 编译网站并将网站发布到 nginx 静态网站目录中。完成上述步骤后,建立批处理文件以便后续操作。

服务器软件安装

安装 Hugo

在 Ubuntu 系统中可以通过 apt 包管理器安装 Hugo Linux | Hugo官方文档 ,执行下面的命令将安装 Hugo 的拓展版本。

1
sudo apt install hugo -y

但是由于长期支持(LTR)的准则,大多数Linux软件包仓库将不包含最新版本,为了获取软件的最新版本,需要从 Release 页面手动安装。

可以从 Hugo 发布页面 上下载对应的 .deb 或 .tar.gz 包手动安装,安装命令如下:

1
2
3
4
5
6
# 从 Github 上下载压缩包
wget https://Github.com/gohugoio/hugo/releases/download/v0.147.7/hugo_extended_0.147.7_linux-amd64.deb
# 安装 Hugo
sudo dpkg -i hugo_extended_0.147.7_linux-amd64.deb
# 检测是否成功安装
hugo version

安装 Git

安装 Git 的命令如下:

1
2
3
4
# 使用包管理器安装 git
sudo apt install git -y
# 检测是否成功安装
Git --version

安装 rsync

Ubuntu 22.04 系统预安装了 rsync 软件,执行 rsync -V 提示找不到命令时可通过下面的命令安装 rsync:

1
sudo apt install rsync

新建远程仓库

采用 ssh 将本地仓库推送远程仓库中,因此需要建立一个用户用于仓库提交。

1
2
3
4
# 添加 git_usr 用户,为了提高安全性可以为 git_usr 用户设置密码
adduser git_usr
# 将 git_usr 用户添加到管理员用户组(避免后续操作没有执行权限)
sudo usermod -aG sudo git_usr

接下来选择一个路径建立 Hugo 博客的存储仓库,这里选择在 git_usr 用户的用户目录建立存储仓库。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 切换到 git_usr 用户
sudo su git_usr
# 将当前路径切换到 git_usr 的用户目录
cd ~
# 创建 Blogs 文件夹用于存放博客文件
mkdir Blogs
# 进入 Blogs 文件夹
cd Blogs
# 将新创建的 git 仓库的默认主分支名称设置为 main
git config --global init.defaultBranch main
# 建立一个空裸仓库(裸仓库是指不包含工作区的 Git 仓库,通常用于共享和协作,在服务器上存放代码,允许其他开发者通过 Git 进行推送和拉取操作)
git init --bare HugoBlogs.git
# 将 HugoBlogs.git 目录及其所有内容的所有者更改为 git_usr 用户和 git_usr 组(用于确保 git_usr 具有远程操作权限)
sudo chown -R git_usr:git_usr HugoBlogs.git
# 建立博客仓库的工作区(用于存放配置、文档等文件)
mkdir HugoBlogs
# 将 HugoBlogs目录及其所有内容的所有者更改为 git_usr 用户和 git_usr 组(用于确保 git_usr 具有远程操作权限)
sudo chown -R git_usr:git_usr HugoBlogs

采用 post-receive 钩子将 Git 的仓库和 Hugo 的工作区进行分离,当 Hugo 博客被推送到 Git 仓库时检出内容到工作目录。

1
2
# 建立 post-receive 钩子文件
vim /home/git_usr/Blogs/HugoBlogs.git/hooks/post-receive

在打开的编辑器中输入如下内容:

1
2
# 从 Git 裸仓库中检出(checkout)文件到工作目录
git --work-tree=/home/git_usr/Blogs/HugoBlogs --git-dir=/home/git_usr/Blogs/HugoBlogs.git checkout -f

使用 :wq 保存并退出,然后为钩子添加执行权限

1
2
# 为 post-receive 添加执行权限(保证 Git 在推送之后能够正确执行自动化操作)
sudo chmod +x /home/git_usr/Blogs/HugoBlogs.git/hooks/post-receive

创建 SSH 密钥

在本地的任意一个文件点击鼠标右键,选择 Git Bash Here ,在打开的 Git Bash 输入如下命令:

1
2
# 创建 ssh 密钥
ssh-keygen -t ed25519 -C "HugoBlogs 仓库密钥"

SSH 密钥将生成到 C:\Users\当前用户\.ssh\目录中,id_ed25519 文件为密钥文件,注意不要泄露给其他人。id_ed25519.pub 为公钥文件,拷贝其中的全部内容用于 SSH 登录。

回到服务器,登录到 git_usr 用户进行 SSH 公钥配置,配置命令如下:

1
2
3
4
5
6
7
8
9
#  将当前路径切换到 git_usr 的用户目录
cd ~
# 建立 .ssh 文件夹用于存放公钥
mkdir -p ~/.ssh
# 编辑公钥文件,将本地创建的公钥文件中所有内容复制到 authorized_keys 中,有多个公钥时一行填写一个公钥
vim ~/.ssh/authorized_keys
# 修改文件权限,保证安全性
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh

启用公钥验证

打开 /etc/ssh/sshd_config 文件,检查是否启用了公钥验证:

1
2
3
4
# 开启公钥验证
PubkeyAuthentication yes
# 禁用密码登录增强安全性 (可选)
PasswordAuthentication no

如果没有启用 PubkeyAuthentication 公钥验证,将公钥验证开启后重新启动 SSH 服务:

1
sudo systemctl restart sshd

建立 rsync 同步目录

git_usr 用户的用户目录建立图片资源的同步目录,在执行下面操作前请确保当前用户为 git_usr,或者手动切换到 git_usr 的用户目录下。

1
2
3
4
5
6
#  将当前路径切换到 git_usr 的用户目录
cd ~/Blogs
# 建立 rysnc 的同步文件夹(用于图片等静态资源的同步)
mkdir HugoStatics
# 将 HugoStatics 目录及其所有内容的所有者更改为 git_usr 用户和 git_usr 组(用于确保 git_usr 具有远程访问权限)
sudo chown -R git_usr:git_usr HugoStatics

执行完上述操作后, git_usr 用户的用户目录结构如下:

1
2
3
4
5
/home/git_usr/Blogs
├── HugoBlogs.git/			<-- git 裸仓库			
├── HugoBlogs/           	<-- git 博客文件工作区
├── HugoStatics/           	<-- rsync 同步文件夹
└── ...

本地仓库设置

在进行博客推送前先进行 ssh 通信测试,为了安全假设 ssh 端口被修改为 6666。

1
2
# ssh 通信测试 -p: 执行端口;@后的 ip 地址为服务器实际地址
ssh -p 6666 [email protected]

如果在创建私钥时指定了密码,这一步需要输入私钥的密码,执行成功后显示的内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-30-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Fri Jun 13 14:02:47 UTC 2025

  System load:  0.14              Processes:             666
  Usage of /:   6.6% of 66.66GB   Users logged in:       1
  Memory usage: 18%               IPv4 address for eth0: 123.45.67.89
  Swap usage:   0%

 * Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
   just raised the bar for easy, resilient and secure K8s cluster deployment.

   https://ubuntu.com/engage/secure-kubernetes-at-the-edge

Expanded Security Maintenance for Applications is not enabled.

初始化本地仓库

进入 01_撰写第一篇文章 中创建的 HugoBlogs 文件夹,打开 Git Bash,初始化 Git 仓库、重命名默认分支并添加远程仓库。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 将新创建的 git 仓库的默认主分支名称设置为 main(只需要执行一次,这里的名称与服务器对应)
git config --global init.defaultBranch main
# 初始化 Git 仓库
git init
# 关闭换行符自动转换(可选)
git config core.autocrlf false
# 添加远程仓库(根据实际修改用户名,IP 地址,端口号和仓库路径)
git remote add origin ssh://[email protected]:6666/home/git_usr/Blogs/HugoBlogs.git
# 查看配置的远程仓库信息
git remote -v

执行完成后,命令行显示的内容如下:

1
2
origin  ssh://[email protected]:6666/home/git_usr/Blogs/HugoBlogs.git (fetch)
origin  ssh://[email protected]:6666/home/git_usr/Blogs/HugoBlogs.git (push)

移除远程仓库的命令如下:

1
2
3
4
# 移除远程仓库
git remote remove origin
# 移除后将不会看到 origin 的任何信息
git remote -v

创建 .gitignore 文件

public 目录和 resources 目录在站点构建时自动创建,static 目录下的内容由 rsync 进行同步,这三个目录不需要 git 进行管理。.gitignore 文件的内容如下:

1
2
3
4
5
6
# 忽略编译生成的文件和文件夹
/public/
/resources/

# 忽略根目录下的 static 文件夹 (rsync 同步)
/static/
警告

需要在每个文件夹前添加 /。不添加 / ,git 会忽略所有同名的子文件夹(递归)。当主题使用 static 目录时,编译网站会缺少文件。

同步 static 目录

在本地安装 rsync 软件,使用 rsync 同步 static 目录。

安装 rsync

这里为 Git for Windows 安装 MSYS2 中的 rsync 软件。进入链接 MSYS2 ,下载如下的4个文件:

1
2
3
4
rsync-3.2.7-2-x86_64.pkg.tar.zst
liblz4-1.10.0-1-x86_64.pkg.tar.zst
libxxhash-0.8.3-1-x86_64.pkg.tar.zst
libzstd-1.5.7-1-x86_64.pkg.tar.zst

下载出来的文件是 .pkg.tar.zst 文件,需要解压后才能使用。可以安装 7-Zip-zstd 进行解压。

将压缩包内的 usr 文件夹的全部文件拷贝到 Git for Windows 的 usr 文件夹内即可完成安装。4个压缩包内的 usr 文件夹的都要拷贝过去。

重要

本地的 git 版本为 git version 2.45.1.windows.1,如果 git 版本不同,可能需要下载其它版本的压缩包。

同步文件夹

进入博客根目录( HugoBlogs 文件夹),执行文件同步命令:

1
rsync -avz -e "ssh -p 6666" static/ [email protected]:/home/git_usr/Blogs/HugoStatics

上面命令执行后,static 目录里面的内容,就都被同步到了 HugoStatics 目录里面。注意命令参数为 static/,而不是 static。使用 static 参数会在 HugoStatics 目录里创建 static 子目录。

从服务器上拉取资源到本地的命令如下:

1
rsync -avz -e "ssh -p 6666" [email protected]:/home/git_usr/Blogs/HugoStatics/ static

rsync 参数的解释如下,详细的解释请参考 rsync 用法教程 - 阮一峰的网络日志

  • -a--archive 表示存档模式,保存所有的元数据,比如修改时间、权限、所有者等,并且软链接也会同步过去。

  • --delete 删除只存在于目标目录、不存在于源目标的文件,即保证目标目录是源目标的镜像。

  • -e 指定使用 SSH 协议传输数据。

  • --exclude 指定排除不进行同步的文件,比如--exclude="*.iso"

  • --exclude-from 指定一个本地文件,里面是需要排除的文件模式,每个模式一行。

  • --existing--ignore-non-existing 表示不同步目标目录中不存在的文件和目录。

  • -h 表示以人类可读的格式输出。

  • -i 表示输出源目录与目标目录之间文件差异的详细情况。

  • --ignore-existing 表示只要该文件在目标目录中已经存在,就跳过去,不再同步这些文件。

  • --include 指定同步时要包括的文件,一般与--exclude 结合使用。

  • -m 指定不同步空目录。

  • --max-size 设置传输的最大文件的大小限制,比如不超过200KB(–max-size=‘200k’)。

  • --min-size 设置传输的最小文件的大小限制,比如不小于10KB(–min-size=10k)。

  • -n--dry-run 模拟将要执行的操作,而并不真的执行。配合 -v 使用,可以看到哪些内容会被同步过去。

  • -r 表示递归,即包含子目录。

  • -u--update 表示同步时跳过目标目录中修改时间更新的文件,即不同步这些有更新的时间戳的文件。

  • -v 表示输出细节。-vv 表示输出更详细的信息,-vvv 表示输出最详细的信息。

  • -z 指定同步时压缩数据。

同步博客文件

在博客根目录( HugoBlogs 文件夹)执行下面的命令来同步博客文件:

1
2
3
4
5
6
# 当前目录下的所有更改都添加到暂存区
git add .
# 将暂存区的更改提交到本地 Git 仓库
git commit -m '创建 Hugo 博客网站'
# 将本地的 main 分支推送到远程仓库
git push -u origin main

批处理文件

本地批处理

可以写一个批处理文件来执行上面的操作,在每次编写完博客后,执行批处理文件将博客的内容上传到服务器上,假设批处理文件和博客根目录( HugoBlogs 文件夹)在同一个文件夹内。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/bash

# rsync 和 git 同步时都需要输入 SSH 私钥的密码,这里开启 SSH 代理。
# 启动 SSH 代理后,只需一次性输入私钥密码,之后的 SSH 连接都将自动使用已添加到代理中的密钥,而无需再次输入密码。
# 启用 SSH 代理
eval $(ssh-agent -s)
# 添加 SSH 私钥到代理
ssh-add ~/.ssh/id_ed25519

# 进入博客文件夹
cd HugoBlogs

# 显示提示信息
echo -e "\033[1;32m开始同步 static 文件夹...\033[0m"
# 同步 static 文件夹
rsync -avz -e "ssh -p 6666" static/ [email protected]:/home/git_usr/Blogs/HugoStatics

# 显示提示信息
echo -e "\033[1;32m开始提交更改...\033[0m"
# 当前目录下的所有更改都添加到暂存区
git add .
# 提示用户输入提交信息
read -p "请输入提交信息: " commit_message
# 将暂存区的更改提交到本地 Git 仓库
git commit -m "$commit_message"
# 将本地的 main 分支推送到远程仓库
git push origin main

# 输出提示信息
echo -e "\033[1;32m推送完成。按Enter键退出...\033[0m"
# 读取用户输入
read

服务器批处理

将博客文件推送到服务器后,使用 hugo 编译博客文件,使用 nginx 部署静态站点。假设静态网站的目录为 /var/www/HugoNotesSite,使用批处理文件自动完成上述操作,批处理文件放在 /home/git_usr/Blogs 文件夹下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 进入博客文件夹
cd /home/git_usr/Blogs/HugoBlogs

# 编译网站
# --gc: 清理未使用的资源文件或生成的文件
# --minify: 对生成的站点内容进行压缩
sudo hugo --gc --minify

# 删除静态网站中的所有内容
sudo rm /var/www/HugoNotesSite/* -rf
# 将博客内容同步到静态网站目录
sudo rsync -a public/ /var/www/HugoNotesSite
# 将所有的图片文件同步到静态网站目录
sudo rsync -a /home/git_usr/Blogs/HugoStatics/ /var/www/HugoNotesSite

# 重启 nginx
sudo systemctl restart nginx