云服务器的自动化部署与运维

云计算是 IT 行业的一大变革,未来云计算将成为商业社会的基础设施,国内阿里、腾讯、京东、美团等一众互联网公司都提供云服务,玩玩服务器变得非常容易了,本文简单地总结一下从项目打包到部署运维的经验。

项目打包

基于 SpringBoot 开发的项目一般使用 maven 或 gradle 来管理,项目打包成 jar 可执行文件都很简单:

1
2
3
4
5
# maven项目打包
mvn clean package

# gradle项目打包
gradlew build

实际中很多时候,比如由于数据库配置文件的更改导致测试无法通过,打包就无法顺利完成,这时我们希望不测试直接打包,使用

1
mvn clean package  -Dmaven.test.skip=true

这条命令可以跳过测试,直接打包,效率提升不少。

启动服务

使用 Xftp 或 WinSCP 等工具登录云主机,把生成的 jar 文件上传到服务器,在 Xshell 中执行:

1
java -jar /root/app.jar

就可以在前台启动项目,这种方式只要控制台关闭,服务就关闭了,通常用来测试项目是否正常运行,正式部署一般用 nohup 命令使服务在后台运行:

1
nohup java -jar /root/app.jar &

部署的时候我们临时指定服务运行的端口号:

1
java -jar app.jar --server.port=2030

也可以让它读取不同的配置文件:

1
java -jar app.jar --spring.profiles.active=dev

或者直接使用外部的配置文件运行:

1
java -jar -Dspring.config.location=app.properties app.jar

关闭和重启服务

程序运行在服务器后台,通过命令行进行关闭和重启管理服务

用进程管理

简单的方式就是通过应用进程来管理,我们知道程序运行的端口号,通过端口号查询进程 ID,就可以直接 kill 掉:

例如使用 lsof -i:5032netstat -anp|grep 5032 可以拿到 5032 端口的 pid,然后直接 kill pid 即可关闭该进程,启动再使用上面的 java -jar 命令即可。

部署多个服务时,可以写一个 Shell 脚本来管理:

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
#!/bin/bash
ser1=2001
ser2=2002
# 启动服务
read -p "start ser1:" val1
if [ "$val1" = "y" ];
then
nohup java -jar /root/ser1-1.0.jar &
echo "ser1 started"
fi

read -p "start ser2:" val2
if [ "$val2" = "y" ];
then
nohup java -jar /root/ser2-1.0.jar &
echo "ser2 started"
fi
# 关闭服务
read -p "stop ser1:" val3
if [ "$val3" = "y" ];
then
kill -9 $(netstat -anp|grep $ser1|awk '{printf $7}'|cut -d/ -f1)
echo "ser1 stopped"
fi

read -p "stop ser2:" val4
if [ "$val4" = "y" ];
then
kill -9 $(netstat -anp|grep $ser2|awk '{printf $7}'|cut -d/ -f1)
echo "ser2 stopped"
fi

注册为服务

除了用进程来管理,另一种更优雅的方式就是通过 Linux 的软连接把应用注册为服务,然后通过 start、stop 这样的命令进行管理。

软连接就类似于 Windows 上的快捷方式,在 /etc/init.d/ 文件夹中创建一个软连接,通过这个软连接来管理应用启动和停止:

1
2
3
4
5
6
7
8
9
10
# 为ser1-1.0.jar创建软连接
ln -s /root/ser1-1.0.jar /etc/init.d/ser1

# 赋予执行权限
chmod +x /etc/init.d/ser1

# 启动应用
/etc/init.d/ser1 start
# 关闭或重启
/etc/init.d/ser1 stop|restart

Python 自动化部署

前面我们使用 Xshell 和 Xftp 等可视化的工具可以很方便地把 jar 文件上传到服务器,然后运行起来,如果你觉得这些工具还是很繁琐,可以使用 Python 脚本实现一键自动上传和部署。

Python 提供了一个 paramiko 库,能够支持 SSH 和 SFTP 协议,可以取代 Xshell 和 Xftp,下面是把本机的 jar 文件上传到服务器并运行的 Python 脚本:

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
# coding=utf-8
import threading
import paramiko

IP = '106.14.19.127'
user = 'root'
password = 'server-pwd'

local_jar = '/target/ser1-1.0.jar'
server_jar = '/root/ser1-1.0.jar'
server_property = '/root/ser1.properties'

def execute_cmds(ip, name, pwd, cmd):
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip, 22, name, pwd, timeout=5)
print '连接成功'
sftp = ssh.open_sftp()
print '正在上传...'
sftp.put(local_jar, server_jar)
print 'jar上传成功'
for m in cmd:
print m
stdin, stdout, stderr = ssh.exec_command(m)
out = stdout.readlines()
for o in out:
print o,
print '运行成功'
ssh.close()
print '关闭连接'
except Exception, error:
print '错误: %s' % (error)

if __name__ == '__main__':
print 'Start deploying %s to server %s' % (server_jar, IP)
cmd = [
'echo Start spring...',
'nohup java -jar -Dspring.config.location=' + server_property + ' ' + server_jar + ' &',
'echo All done.'
]
a = threading.Thread(target=execute_cmds, args=(IP, user, password, cmd))
a.start()