博客目前部署环境及迁移脚本

现用的阿里云ECS服务器已服役四年,几个月后就要到期了。为简化后续网站迁移流程,写了一些脚本。

其实打包成自定义镜像更简单,但那样磁盘占用会有许多冗余(很多不怎么用的软件,实在记不清了…)。

博客迁移

在新的服务器中执行以下命令即可完成迁移:

1
2
# 链接中的 *** 要改一下
curl -s https://wlizhi.cc/*** | sh

等它跑完(大概要两分多钟),将域名解析指向新服务器地址,迁移完成。

博客部署环境

Latest

  • 阿里云ECS,操作系统:Alibaba Cloud Linux 3.2104 LTS 64位 快速启动版
  • docker-ce:latest
  • nginx:latest
  • springboot-auto-deploy(内部会执行本地指令完成热部署。通过 Webhooks 回调或 curl 调用)
  • 若干脚本

自动部署: 本地编写/博客外链gitee线上修改,并提交md文档 -> 触发webhooks回调热部署。以下为热部署步骤:

  1. git 重置本地md文档、更新文档。
  2. 构建html到指定的临时目录(这个过程看机器配置可能要花费1-5秒)。
  3. 删除博客服务的html文件。
  4. 将临时目录中的html文件移动到博客服务对应的目录。

1.0(目前做备用方案了)

  • 阿里云ECS,系统版本:CentOS7.6
  • docker-ce:latest
  • nginx:latest
  • springboot-auto-deploy(内部会执行本地指令完成热部署。通过 Webhooks 回调或 curl 调用)
  • 若干脚本(nginx配置包、异步初始化博客、ssl证书检测、日志清理、博客清理、博客初始化、auto-deploy-start/stop)

自动部署: 本地编写md文档、提交 -> 本地构建html -> 提交html到gitee -> 触发webhooks回调热部署。

其他

备注

1.0版本部署时服务无暂停,切换平滑。修改md文件后需本地构建并提交html后才会自动部署。

latest版本部署时有暂停(步骤3和步骤4,毫秒级)。修改md文档后就会自动部署,这完美支持了在线编辑。

使用临时目录,是因为构建html需要一些时间(3.5秒左右),而临时目录可以作为缓冲、使得构建期间服务不必暂停。

截取一段自动部署的日志:

 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
2024-06-24 15:05:47.164  INFO 50464 --- [deploy-thread-1] c.w.d.service.impl.DeployServiceImpl     : 收到通知,开始执行部署任务...
2024-06-24 15:05:47.177  INFO 50464 --- [deploy-thread-1] c.w.deploy.util.ShellExecuteSupport      : current workDir:/root 
2024-06-24 15:05:47.178  INFO 50464 --- [deploy-thread-1] c.w.deploy.util.ShellExecuteSupport      : execute command: deploy_blog.sh
2024-06-24 15:05:53.845  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            : HEAD is now at f0e4ffc 热部署服务包名称修改。
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            : Updating f0e4ffc..9586beb
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            : Fast-forward
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            :  content/posts/me/blog/website-migration/index.md | 2 +-
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            :  1 file changed, 1 insertion(+), 1 deletion(-)
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            : Start building sites … 
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            : hugo v0.127.0-74e0f3bd63c51f3c7a0f07a7c779eec9e922957e+extended linux/amd64 BuildDate=2024-06-05T10:27:59Z VendorInfo=gohugoio
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            : 
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            : 
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            :                    | ZH-CN  
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            : -------------------+--------
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            :   Pages            |   193  
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            :   Paginator pages  |    15  
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            :   Non-page files   |     9  
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            :   Static files     |   398  
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            :   Processed images |     0  
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            :   Aliases          |    50  
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            :   Cleaned          |     0  
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            : 
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            : Total in 3954 ms
2024-06-24 15:05:53.846  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            : Mon Jun 24 03:05:53 PM CST 2024 热部署完成,服务暂停时间: 3.408毫秒.
2024-06-24 15:05:53.847  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            : From https://gitee.com/wlizhi/blog
2024-06-24 15:05:53.847  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            :  * branch            master     -> FETCH_HEAD
2024-06-24 15:05:53.848  INFO 50464 --- [deploy-thread-1] cc.wlizhi.deploy.util.LogUtil            :    f0e4ffc..9586beb  master     -> origin/master
2024-06-24 15:05:53.848  INFO 50464 --- [deploy-thread-1] c.w.d.service.impl.DeployServiceImpl     : ^_^ 真棒,部署成功了,耗时 6684ms ^_^

迁移脚本 Latest

run.sh

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#!/bin/bash

BLOG_ZIP_URL=https://***
BOOTSTRAP_SHELL_PATH=/**/?.sh

# 计时
start_time=$(date +%s)
cd /root
BLOG_ZIP_NAME=$(basename ${BLOG_ZIP_URL});
yum install -y unzip
wget ${BLOG_ZIP_URL}
unzip ${BLOG_ZIP_NAME} -d /
sh ${BOOTSTRAP_SHELL_PATH}

rm -rf /__MACOSX
rm -rf ${BLOG_ZIP_NAME}

echo "$(date) 博客搭建完成,脚本 run.sh 共执行了 $(($(date +%s) - start_time))s."

bootstrap.sh

  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
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/bin/bash

# 此脚本用来初始化一个博客服务器,包含以下内容:
#	1. 安装docker。
#	2. 拉取nginx镜像。
#	3. 拉取jdk安装包、解压、设置环境变量。
#	4. 初始化 auto deploy。
#	5. 初始化 hugo。
#	6. 初始化定时任务。
#	7. 安装git、拉取博客代码。
#	8. 构建博客代码、生成html文件。
#	9. 启动自动发布钩子服务。
#	10. 替换default.conf中的inner_host为本机内网ip。
#	11. 启动nginx容器。

# ----- 私有配置 -----
# 博客路径
GIT_USER_NAME=
GIT_EMAIL=
GIT_TOKEN=

BLOG_DIR=
BLOG_CODE_DIR=
GIT_CLONE_URL=
# 源文件路径
SRC_DIR=
# 自动发布服务路径
AUTO_DEPLOY_DIR=
# 自动发布服务启动脚本
AUTO_DEPLOY_SHELL_PATH=
# nginx配置文件路径
NGINX_DIR=
NGINX_CONFIG_PATH=
# nginx配置文件中,阿里云内网地址占位符
NGINX_INNER_NETWORK_IP_PLACEHOLDER=
# hugo的安装目录
HUGO_DIR=
# shell脚本路径
SHELL_DIR=
# 自动发布脚本路径
DEPLOY_BLOG_SHELL_PATH=
# shell日志路径
SHELL_LOG_DIR=
# JDK路径
JAVA_DIR=

# ----- 公有配置 -----
# JDK URL
JDK_URL=https://mirrors.huaweicloud.com/openjdk/11.0.2/openjdk-11.0.2_linux-x64_bin.tar.gz
# docker安装包源 docker-ce.repo
DOCKER_CE_REPO=https://mirrors.huaweicloud.com/docker-ce/linux/centos/docker-ce.repo
# 镜像加速
# REGISTRY_MIRROR="https://0c697b6bf180f3af0f41c019dbcccbc0.mirror.swr.myhuaweicloud.com"
REGISTRY_MIRROR="https://kj2sj2l6.mirror.aliyuncs.com"

# 计时
start_time=$(date +%s)

install_docker(){
  sudo yum remove docker \
                    docker-client \
                    docker-client-latest \
                    docker-common \
                    docker-latest \
                    docker-latest-logrotate \
                    docker-logrotate \
                    docker-engine

  # Step 1: 安装必要工具
  sudo yum install -y yum-utils device-mapper-persistent-data lvm2
  # Step 2: 添加软件源信息
  wget -O /etc/yum.repos.d/docker-ce.repo ${DOCKER_CE_REPO}
  # Step 3
  sudo sed -i 's+download.docker.com+mirrors.huaweicloud.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
  # Step 4: 更新并安装Docker-CE
  sudo yum makecache fast

  sudo yum -y install docker-ce

  mkdir -p /etc/docker
  echo '{ "registry-mirrors": [ "'$REGISTRY_MIRROR'" ] }' >> /etc/docker/daemon.json

  sudo systemctl enable docker
  sudo systemctl start docker
}

# 1. 安装docker。
docker_start_time=$(date +%s)
echo '>>>>>>>>>> docker install starting...'
install_docker
echo '>>>>>>>>>> docker installed.'
echo "$(date) Docker executed for $(($(date +%s) - docker_start_time))s,completed."

# 2. 拉取nginx镜像。
nginx_init_start_time=$(date +%s)
echo '>>>>>>>>>> docker pull nginx starting...'
docker pull nginx
echo '>>>>>>>>>> docker pull nginx end...'
echo "$(date) Nginx executed for $(($(date +%s) - nginx_init_start_time))s,completed."

# 3. 拉取jdk安装包、解压、设置环境变量。
jdk_start_time=$(date +%s)
echo '>>>>>>>>>> jdk install starting...'
JDK_TAR_FILE_PATH=${SRC_DIR}/$(basename "$JDK_URL")
wget -P ${SRC_DIR} ${JDK_URL}
JDK_DIR_NAME=`tar -tzf ${JDK_TAR_FILE_PATH} | grep '/' | head -n 1 | awk -F/ '{print $1}'`
tar -xzvf ${JDK_TAR_FILE_PATH} -C ${BLOG_DIR}
sudo echo "" >> /etc/profile
sudo echo "export JAVA_HOME=${BLOG_DIR}/${JDK_DIR_NAME}" >> /etc/profile
sudo echo 'export PATH=$PATH:$JAVA_HOME/bin' >> /etc/profile
source /etc/profile
java -version
echo '>>>>>>>>>> jdk install end...'
echo "$(date) jdk executed for $(($(date +%s) - jdk_start_time))s,completed."

# 4. 初始化 auto deploy。
echo '>>>>>>>>>> auto deploy init starting...'
sudo echo 'export PATH=$PATH:'${AUTO_DEPLOY_DIR} >> /etc/profile
source /etc/profile
rm -rf ${JDK_TAR_FILE_PATH}
echo '>>>>>>>>>> auto deploy init end.'

# 5. 初始化 hugo。
echo '>>>>>>>>>> hugo init starting...'
sudo echo 'export PATH=$PATH:'${HUGO_DIR} >> /etc/profile
source /etc/profile
echo '>>>>>>>>>> hugo init end.'

# 6. 初始化定时任务。
echo '>>>>>>>>>> crontab init starting...'
crontab -r
(crontab -l 2>/dev/null; echo "* * * * * /bin/bash ${SHELL_DIR}/cert_unzip.sh >> ${SHELL_LOG_DIR}/unzip.log 2>&1") | crontab -
(crontab -l 2>/dev/null; echo "* * * * * /bin/bash ${SHELL_DIR}/clean_logs.sh >> ${SHELL_LOG_DIR}/clean.log 2>&1") | crontab -
echo '>>>>>>>>>> crontab init end.'

# 7. 安装git、拉取博客代码。
GIT_CLONE_START_TIME=$(date +%s)
echo '>>>>>>>>>> git clone code starting...'
yum install -y git
git config --global user.name $GIT_USER_NAME
git config --global user.email $GIT_EMAIL
git config --global credential.helper store
git clone ${GIT_CLONE_URL} ${BLOG_CODE_DIR}
echo '>>>>>>>>>> git clone code end.'
echo "$(date) Git executed for $(($(date +%s) - GIT_CLONE_START_TIME))s,completed."

# 8. 构建博客代码、生成html文件。
HTML_START_TIME=$(date +%s)
echo '>>>>>>>>>> generate html starting...'
sh ${DEPLOY_BLOG_SHELL_PATH}
echo '>>>>>>>>>> generate html end.'
echo "$(date) Generate html executed for $(($(date +%s) - GIT_CLONE_START_TIME))s,completed."

# 9. 启动自动发布钩子服务。
sh ${AUTO_DEPLOY_SHELL_PATH}

# 10. 替换default.conf中的inner_host为本机内网ip.
# 使用sed命令替换文件中的字符串。
sed -i "s/$NGINX_INNER_NETWORK_IP_PLACEHOLDER/$(hostname -i)/g" "$NGINX_CONFIG_PATH"

# 11. 启动nginx容器。
docker  run -d --name nginx -v /blog/nginx:/etc/nginx -p 80:80 -p 443:443 -e TZ=Asia/Shanghai nginx

echo "$(date) Executed for $(($(date +%s) - start_time))s,completed."

deploy_blog.sh

 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
#!/bin/bash

# 博客自动发布方案:
#   1. 构建html到临时目录(相对耗时)。
#   2. 删除html目录。
#   3. 将html临时目录移动到html目录。
# 使用临时目录中转的好处:构建html的过程中依然可以访问。

# 博客源代码目录
BLOG_CODE_DIR=
# 博客html临时目录
BLOG_HTML_TEMP_DIR=
# 博客html文件目录
BLOG_HTML_DIR=
# hugo指令目录
HUGO_PATH=

cd ${BLOG_CODE_DIR}
git reset --hard origin/master
git pull origin master
rm -rf ${BLOG_HTML_TEMP_DIR}
${HUGO_PATH} -s ${BLOG_CODE_DIR} -d ${BLOG_HTML_TEMP_DIR}
rm -rf ${BLOG_HTML_DIR}

stop_word_start_timestamp=$(date +%s%N) 
mv ${BLOG_HTML_TEMP_DIR} ${BLOG_HTML_DIR}
ns_diff=$(($(date +%s%N) - stop_word_start_timestamp));
ms_diff=$(awk -v ns="$ns_diff" 'BEGIN {printf "%.3f", ns/1000000}') 
echo "$(date) 热部署完成,服务暂停时间: ${ms_diff}毫秒."

cert_unzip.sh、clean_logs.sh、start-blog-deploy.sh、stop-blog-deploy.sh 与1.0版本脚本一致。

迁移脚本 1.0

迁移脚本执行流程
  1. 安装常用工具包、docker、配置国内镜像源。
  2. 从原服务器下载nginx配置包、安装nginx、配置nginx。
  3. 拉取 openJdk、安装jdk、配置并刷新环境变量。
  4. 从原服务器下载 auto_deploy 服务、及启动、停机脚本。
  5. 从原服务器拉取引导脚本并执行。

其中:

  • nginx配置包:将预设值的nginx配置压缩放置到博客某个目录下,以供迁移时下载。
  • openJdk: 从华为云镜像源拉取。
  • 博客自动发布包:从原博客服务器拉取。
  • 引导脚本:从原博客服务器拉取。
    • 日志清理:由引导脚本级联调用运行。
    • ssl证书检测:由引导脚本级联调用运行。
    • 自动发布服务启动:由引导脚本级联调用运行。
    • 定时任务创建:由引导脚本级联调用运行。

run.sh

  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
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/bin/bash

# 博客服务器初始化,博客迁移。

# ----- 路径相关配置 -----
# 博客路径
BLOG_PATH=/xxx
# 自动发布服务路径
AUTO_DEPLOY_PATH=/xxx
# nginx配置文件路径
NGINX_PATH=/xxx
# shell脚本路径
SHELL_PATH=/xxx
# shell日志路径
SHELL_LOG_PATH=/xxx
# 源文件路径
SRC_PATH=/xxx

# ----- 私有软件包、脚本地址配置 -----
# 下载的jdk包默认解压名称。
JDK_DIR_NAME=xxx
# 引导脚本文件名
BOOTSTRAP_FILE_NAME=xxx
# nginx配置文件
NGINX_CONFIG_FILE_URL=xxx
# 自动部署jar包地址、jar包启动、停机脚本。
AUTO_DEPLOY_JAR_URL=xxx
AUTO_DEPLOY_START_URL=xxx
AUTO_DEPLOY_STOP_URL=xxx
# 博客服务需要用到的shell脚本
BLOG_SHELL_URL=xxx

# ----- 公有软件包、镜像源等配置 -----
# JDK URL
JDK_URL=https://mirrors.huaweicloud.com/openjdk/11.0.2/openjdk-11.0.2_linux-x64_bin.tar.gz
# docker安装包源 docker-ce.repo
DOCKER_CE_REPO=https://mirrors.huaweicloud.com/docker-ce/linux/centos/docker-ce.repo
# yum源
YUM_REPO=http://mirrors.aliyun.com/repo/Centos-7.repo

# 计时
start_time=$(date +%s)

# 安装docker
install_docker(){
  sudo yum remove docker \
                    docker-client \
                    docker-client-latest \
                    docker-common \
                    docker-latest \
                    docker-latest-logrotate \
                    docker-logrotate \
                    docker-engine

  # Step 1: 安装必要工具
  sudo yum install -y yum-utils device-mapper-persistent-data lvm2
  # Step 2: 添加软件源信息
  wget -O /etc/yum.repos.d/docker-ce.repo ${DOCKER_CE_REPO}
  # Step 3
  sudo sed -i 's+download.docker.com+mirrors.huaweicloud.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
  # Step 4: 更新并安装Docker-CE
  sudo yum makecache fast

  sudo yum -y install docker-ce

  mkdir -p /etc/docker
  echo '{
          "registry-mirrors": ["https://kj2sj2l6.mirror.aliyuncs.com"]
        }' >> /etc/docker/daemon.json

  sudo systemctl enable docker
  sudo systemctl start docker
}

echo '>>>>>>>>>> docker install starting...'
install_docker
echo '>>>>>>>>>> docker installed.'

# 修改为阿里yum源
wget -O /etc/yum.repos.d/CentOS-Base.repo ${YUM_REPO}
yum clean all
yum makecache
sudo yum install -y git unzip

echo '>>>>>>>>>> docker init nginx starting...'
mkdir -p ${BLOG_PATH} ${AUTO_DEPLOY_PATH} ${NGINX_PATH} ${SHELL_PATH} ${SRC_PATH}
docker pull nginx
docker run -d --name n1 nginx
sleep 3
docker cp n1:/etc/nginx ${BLOG_PATH}
docker stop n1 && docker rm n1
# 下载解压nginx配置文件
wget -O ${SRC_PATH}/nginx.zip ${NGINX_CONFIG_FILE_URL}
unzip -o ${SRC_PATH}/nginx.zip -d ${SRC_PATH}

unalias cp
cp -rf ${SRC_PATH}/nginx/* ${NGINX_PATH}

rm -rf ${SRC_PATH}/nginx
rm -rf ${SRC_PATH}/nginx.zip
rm -rf ${BLOG_PATH}/__MACOSX
rm -rf ${NGINX_PATH}/__MACOSX
echo '>>>>>>>>>> docker init nginx end...'

echo '>>>>>>>>>> jdk install starting...'
cd ${SRC_PATH}
wget ${JDK_URL}
tar -xzvf openjdk-11.0.2_linux-x64_bin.tar.gz
rm -rf openjdk-11.0.2_linux-x64_bin.tar.gz
rm -rf ../jdk-11.0.2
mv jdk-11.0.2 ../
sudo echo "" >> /etc/profile
sudo echo "export JAVA_HOME=${BLOG_PATH}/${JDK_DIR_NAME}" >> /etc/profile
sudo echo 'export PATH=$PATH:$JAVA_HOME/bin' >> /etc/profile
source /etc/profile
java -version
echo '>>>>>>>>>> jdk install end...'

echo '>>>>>>>>>> auto deploy install starting...'
cd ${AUTO_DEPLOY_PATH}
wget -P ${AUTO_DEPLOY_PATH} ${AUTO_DEPLOY_JAR_URL}
wget -P ${AUTO_DEPLOY_PATH} ${AUTO_DEPLOY_START_URL}
wget -P ${AUTO_DEPLOY_PATH} ${AUTO_DEPLOY_STOP_URL}
chmod +x ${AUTO_DEPLOY_PATH}/start-blog-deploy.sh
chmod +x ${AUTO_DEPLOY_PATH}/stop-blog-deploy.sh

sudo echo 'export PATH=$PATH:'${AUTO_DEPLOY_PATH} >> /etc/profile
rm -rf ${BLOG_PATH}/__MACOSX
echo '>>>>>>>>>> auto deploy install end.'

echo '>>>>>>>>>> blog shell install starting...'
wget -P ${SRC_PATH} ${BLOG_SHELL_URL}
unzip -o ${SRC_PATH}/shell.zip -d ${BLOG_PATH}
rm -rf ${SRC_PATH}/shell.zip
rm -rf ${BLOG_PATH}/__MACOSX

mkdir -p ${SHELL_PATH}/logs
crontab -r
(crontab -l 2>/dev/null; echo "* * * * * /bin/bash ${SHELL_PATH}/cert_unzip.sh >> ${SHELL_LOG_PATH}/unzip.log 2>&1") | crontab -
(crontab -l 2>/dev/null; echo "* * * * * /bin/bash ${SHELL_PATH}/clean_logs.sh >> ${SHELL_LOG_PATH}/clean.log 2>&1") | crontab -
echo '>>>>>>>>>> blog shell install end.'

echo '>>>>>>>>>> blog shell install starting...'
sh ${SHELL_PATH}/${BOOTSTRAP_FILE_NAME}

echo "$(date) Executed for $(($(date +%s) - start_time))s,completed."

start-blog-deploy.sh

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#!/bin/bash

current_dir=xxx
process_num=`jps -l |grep xxx | awk '{print $1}'`

if test -z $process_num
then
    nohup java -jar -Dserver.port=8081 -Xms60m -Xmx60m -Xmn35m -XX:MaxMetaspaceSize=60m -Xss300k ${current_dir}/xxx --spring.profiles.active=prod > ${current_dir}/auto_deploy.log 2>&1 &

    echo 'The java porcess started.'
    process_num=`jps -l |grep xxx | awk '{print $1}'`
    echo "The java process number is ${process_num}."
else
    echo "The java process is already exists."
fi
吐槽
PS:服务器配置实在太低了,运行一个springboot程序都得精打细算。jstat调了十几次,最终把堆调整为60m、方法区60m,再低点启动正常,热部署时可能就OOM了,emm…

stop-blog-deploy.sh

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/bin/bash

process_num=`jps -l |grep xxx | awk '{print $1}'`

if test -z $process_num
then
    echo 'The java porcess is not exists.'
else
    echo "The java process number is ${process_num}."
    `kill -9 $process_num`
    echo 'The java process is stopped.'
fi

bootstrap.sh

 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

# 此脚本用来初始化博客服务器.在实例创建时,可以通过自定义用户数据执行此脚本.
# 初始化内容包括: 
#   1. 自动拉取博客html到xxx.
#   2. 启动自动发布钩子服务.
#   3. 替换nginx配置文件default.conf中的变量值.
#   3. 启动一个nginx容器. 

# html文件存放位置.
BLOG_HTML_DIR=xx
# 拉取HTML文件的git仓库地址,这个仓库必须是公开的.
GIT_REPO=xxx
# nginx默认配置文件地址.
nginxConfPath=xxx
AUTO_DEPLOY_START_SHELL=xxx
# 配置文件中的占位符字符串及替换后的值.
oldstr='$aliyun_ecs_inner_network_ip_address'
newstr="$(hostname -i)"

# 从git仓库拉取html
git clone $GIT_REPO $BLOG_HTML_DIR

# 启动自动发布钩子服务
sh ${AUTO_DEPLOY_START_SHELL}

# 替换default.conf中的inner_host为本机内网ip.
# 使用sed命令替换文件中的字符串  
sed -i "s/$oldstr/$newstr/g" "$nginxConfPath"

# 启动nginx容器
docker  run -d --name nginx -v xxx:/etc/nginx -p 80:80 -p 443:443 -e TZ=Asia/Shanghai nginx

clean_logs

 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/bin/bash  
  
# 定义日志文件路径和新的文件名  
LOG_FILES=("xxx/init.log" "xxx/unzip.log" "xxx/clean.log" "xxx/auto_deploy.log")  
NEW_LOG_FILES=("xxx/init_archived.log" "xxx/unzip_archived.log" "xxx/clean_archived.log" "xxx/auto_deploy_archived.log")  
  
# 阈值(1M字节)  
THRESHOLD=$((1024 * 1024))  

echo "clean logs starting..."  
# 遍历日志文件数组  
for ((i=0; i<${#LOG_FILES[@]}; i++)); do  
    LOG_FILE="${LOG_FILES[$i]}"  
    NEW_LOG_FILE="${NEW_LOG_FILES[$i]}"  
  
    # 检查日志文件是否存在  
    if [ ! -f "$LOG_FILE" ]; then  
        echo "$(date) 日志文件 $LOG_FILE 不存在"  
        continue  
    fi  
  
    # 获取日志文件大小(字节)  
    LOG_SIZE=$(stat -c%s "$LOG_FILE")  
  
    # 检查文件大小是否超过阈值  
    if [ $LOG_SIZE -gt $THRESHOLD ]; then  
        # 如果NEW_LOG_FILE已经存在,则先删除它  
        if [ -f "$NEW_LOG_FILE" ]; then  
            rm -f "$NEW_LOG_FILE"  
        fi  
  
        # 重命名LOG_FILE为NEW_LOG_FILE  
        mv "$LOG_FILE" "$NEW_LOG_FILE"  
  
        # 检查重命名是否成功  
        if [ -f "$NEW_LOG_FILE" ]; then  
            echo "$(date) 日志文件 $LOG_FILE 已重命名为 $NEW_LOG_FILE"  
        else  
            echo "$(date) 重命名日志文件 $LOG_FILE 失败"  
        fi  
    else  
        echo "$(date) 日志文件 $LOG_FILE 的大小未超过1M"  
    fi  
done

echo "clean logs ended."
echo ""

cert_unzip.sh

 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/bin/bash  
  
# 每次休眠时间,单位秒
per_sleep_sec=5
# 最长执行时间,单位秒
max_exe_sec=60
# ssl证书自动解压目录
DIRECTORY_TO_CHECK=xxx

# 初始化开始时间  
start_time=$(date +%s)

certUnzip(){
    echo "$(date) Starting checking directory: $DIRECTORY_TO_CHECK"
    # 检查目录是否存在  
    if [ ! -d "$DIRECTORY_TO_CHECK" ]; then
        echo "$(date) Error: Directory '$DIRECTORY_TO_CHECK' does not exist."  
        exit 1
    fi

    # 查找并处理目录下的所有.zip文件  
    for zip_file in "$DIRECTORY_TO_CHECK"/*.zip; do
        if [ -f "$zip_file" ]; then
            # 获取.zip文件的名称(不带路径)  
            filename=$(basename "$zip_file")
            # 获取.zip文件的基础名(不带.zip扩展名)  
            basename_without_ext="${filename%.*}"
            # 解压.zip文件到当前目录(或指定目录)  
            unzip -o "$zip_file" -d "$DIRECTORY_TO_CHECK"
            # 检查解压是否成功(这里只是一个简单的检查,实际上unzip的返回值会告诉你是否成功)  
            if [ $? -eq 0 ]; then
                # 如果解压成功,则删除原始的.zip文件  
                rm "$zip_file"
                echo "$(date) Unzipped and deleted: $zip_file"
                docker restart nginx && echo "$(date) docker restart nginx successful." || echo "$(date) docker restart nginx failed."
            else
                echo "$(date) Error unzipping: $zip_file"  
            fi
        fi
    done
    echo "$(date) Finished checking directory: $DIRECTORY_TO_CHECK"
}

# 循环条件:(已执行的秒数) 小于 (最大执行时间阈值 - 休眠间隔秒数),小于号之后不采用阈值,是为了保证总执行时长一定小于阈值。 
while (( $(date +%s) - start_time < $((max_exe_sec - per_sleep_sec)) )); do
    certUnzip
    sleep $per_sleep_sec
done  

echo "$(date) Executed for $(($(date +%s) - start_time))s, Loop finished."