适用Serverless网站静态资源Jenkins增量发布的Shell脚本

83 阅读3分钟

脚本主要作用

简单说就是提取文件夹中的增量变化文件。

假设有A、B、C三个文件夹,A为本次新产生的文件夹,B为存储上次A文件夹的文件,用于比较,C为提取后的增量文件文件夹。执行脚本对A和B(即A的上个版本)进行比较,将A中新增或修改的文件(不含删除)提取到C里。

接下来C怎么用就看你自己的需求了。

适用场景举例

当网站通过ssr或csr编译发布后产生了一些静态资源A,如css、js等,当然也可以是其他场景下产生的静态资源,你希望将这些变更的部分C发布到线上去,没变化就没必要浪费资源再覆盖一次,同时又要保证线上的老的版本还能继续访问,比如CDN一般会缓存老的页面资源,请求老的js、css,文件只增不减,可以避免用户请求不到资源,使页面出现裸奔状态。

当然每次发布都会增加不少的资源文件,使得线上的存储越来越臃肿,不过文件都很小,即使只增不减,几年下来也大不到哪里去,个人感觉可以忽略,当然有能力者也可以自己写个清理程序。

脚本代码参考

#!/bin/sh
# 本脚本主要是比较并提取出发布前后两个文件夹的差异文件到一个diff目录中,然后使用diff进行增量发布到线上

# 比较发布前后两个文件夹的差异,导出到dist.diff文件中
WORKSPACE=$1 # 工作目录,执行脚本时传递过来的参数变量
curr_dir=$WORKSPACE"/dist" # 即文件夹A,路径可以自己定义
last_dir=$WORKSPACE"/old" # 即文件夹B,路径可以自己定义
diff_dir=$WORKSPACE"/diff" # 即文件夹C,路径可以自己定义
diff_file=$WORKSPACE"/dist.diff" # 比较后的差异信息文件,里面记录的哪些文件的变更,路径可以自己定义
diff -q -r -b $curr_dir $last_dir > $diff_file # 比较A和B的差异,产生差异信息文件dist.diff

# diff_dir目录如果不存在则创建
if [ ! -d $diff_dir ]; then
    mkdir -p $diff_dir
else
    # 如果dist.diff文件存在并且内容不为空,表示有新内容需要发布,则先清空diff_dir文件夹;
    # 如果没有新发布,则先不清空diff_dir文件夹,可重复使用上次的发布,避免一次发布失败,二次发布时空空如也。
    if [ -f $diff_file ] && [ -s $diff_file ]; then
        rm -rf $diff_dir/*
    fi
fi

# 打印出差异记录到中控台
echo "以下是差异文件清单"
cat $diff_file

echo "--------------------copy A to C begin------------------------"

# 复制serverless.yml文件到发布目录(注意:这个文件是Serverless的配置文件比较,没有此文件的可以忽略)
if [ ! -f $diff_dir/serverless.yml ]; then
    echo "+ $diff_dir/serverless.yml"
    cp -f $curr_dir/serverless.yml $diff_dir/serverless.yml
fi

# 循环读取每一行差异记录
cat $diff_file |while read line
do
    # 只有一边有的情况,取出地址
    if [[ $line == 'Only in '* ]]; then
    
        # 字符串提取参考文章:https://www.cnblogs.com/superbaby11/p/17007867.html
        # 取‘Only in ’后面的字符串
        path=${line#*'Only in '}
        # 路径中的‘: ’替换为‘/’
		path=${path/': '/\/}
        
        # 地址必须是工作目录的路径,防止处理非法地址导致意外发生
        if [[ $path != $WORKSPACE* ]]; then
            continue
        fi
        
        # 如果last_dir存在而curr_dir不存在,则删除last_dir
        if [[ $path == $last_dir* ]]; then
            rm -rf $path
            echo '- ' $path
        
        # 如果last_dir不存在而curr_dir存在,则添加
        else
        
            # 如果是个目录,则全部复制过去
            if [ -d $path ]; then
                # 先添加到diff_dir中
                tar_dir=${path/$curr_dir/$diff_dir}
                if [ ! -d $tar_dir ]; then
                    mkdir -p $tar_dir
                fi
                cp -a $path/* $tar_dir
                
                # 再添加到last_dir中
                tar_dir2=${path/$curr_dir/$last_dir}
                if [ ! -d $tar_dir2 ]; then
                    mkdir -p $tar_dir2
                fi
                cp -a $path/* $tar_dir2
                
                echo '+ ' $path
            # 否则就是文件,也复制过去
            else
                # 先添加到diff_dir中
                tar_file=${path/$curr_dir/$diff_dir}
                tar_dir=$(dirname $tar_file)
                if [ ! -d $tar_dir ]; then
                    mkdir -p $tar_dir
                fi
                cp -f $path $tar_file
                
                # 再添加到last_dir中
                tar_file2=${path/$curr_dir/$last_dir}
                tar_dir2=$(dirname $tar_file2)
                if [ ! -d $tar_dir2 ]; then
                    mkdir -p $tar_dir2
                fi
                cp -f $path $tar_file2
                
                echo '+ ' $path
            fi
        fi
    
    # 两边都有,但有差异,需要覆盖过去
    elif [[ $line == 'Files '*' and '*' differ' ]]; then
    
        # 取‘Files ’后面的字符串
        path=${line#*'Files '}
        # 取‘ and’前面的字符串
        path=${path%%' and'*}
        
        # 先添加到diff_dir中
        tar_file=${path/$curr_dir/$diff_dir}
        tar_dir=$(dirname $tar_file)
        if [ ! -d $tar_dir ]; then
        mkdir -p $tar_dir
        fi
        cp -f $path $tar_file

        # 再添加到last_dir中
        tar_file2=${path/$curr_dir/$last_dir}
        tar_dir2=$(dirname $tar_file2)
        if [ ! -d $tar_dir2 ]; then
        mkdir -p $tar_dir2
        fi
        cp -f $path $tar_file2

        echo '> ' $path
    
    # 如果发现有其他情况,显示出来
    else
        echo "? " $line
    fi
done
echo "--------------------copy end------------------------"

执行方法参考

将以上代码保存为 diff-extract.sh,然后执行如下,后面地址参数改成自己的:

./diff-extract.sh /home/jenkins/workspace/aaa