让Aws S3 只同步 Hexo 内容有变化的文件

问题描述

发现Aws S3 sync 在同步Hexo 生成的网站内容时,几乎总是同步所有文件,那些内容没有发生改变但文件最后修改时间发生改变的文件也被同步了,造成了Aws S3写操作流量的浪费,原因如下

  1. Aws S3 sync 命令的同步的策略

    1. 判断文件大小是否发生变化
    2. 比较文件最后的修改日期

    如果某个文件的这两项中的其中一项发生变化,则这个文件被同步

  2. Hexo生成文章

    即使仅更新一篇文章,使用hexo g命令后,几乎所有文件的最后修改时间都被更新了。目前来看,Hexo更新内容的算法还有待改进,有些地方还是有优化空间的

由于以上两点,造成了Aws S3写流量的浪费

解决方案

只同步内容有改变的文件

  1. 通过git diff 命令找出此次提交发生变化的文件。这里不用git log的原因是log命令会有多余的输出,不利于后面编写脚本
  2. 使用aws s3 cp把发生变化的文件同步到Aws S3,这样就大大节省了Aws S3写操作的流量

编写脚本

1
2
3
#!/bin/bash
git diff HEAD~1 HEAD --stat --name-only | awk '{cmd="aws s3 cp "$1" s3://your-butket/"$1" --exclude '.gitignore'";system(cmd)}'

放到项目根目录执行,此脚本只会同步那些内容有修改的文件,内容没有修改,但最后修改时间被更新的文件不会被同步,大大节省了Aws S3的写流量

后记,奇怪的git diff输出

发现git diff --stat输出时,如果输出到屏幕,那些长路径名是可以正常显示的,但如果输出到文件,则长路径就会被省略显示。

1
2
3
4
5
6
7
8
9
10
11
# 长路径名
looooooooooong_path_name/index.html
# 在输出到屏幕时是可以正常显示的
> git diff --stat
> looooooooooong_path_name/index.html
# 但如果输出到文件,路径名就变成了:".../index.html"
> git diff --stat > diff.log
> cat diff.log
> .../index.html

为了解决这个问题,需要执行 git diff --stat --name-only, 输出到文件也可以正常显示长路径名了

1
2
3
> git diff --stat --name-only > diff.log
> cat diff.log
> looooooooooong_path_name/index.html