自己写的发布小工具
maven依赖:
<dependencies>
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>262</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
实体类:
ProjectInfo:项目信息
/
* 项目信息
*
* @author lzlg
*/
public class ProjectInfo {
/
* 项目名称
*/
private String projectName;
/
* 项目版本
*/
private String version;
/
* 项目本地地址
*/
private String localPath;
/
* 项目部署在服务器的地址
*/
private String deployPath;
public ProjectInfo(String projectName, String version, String localPath, String deployPath) {
this.projectName = projectName;
this.version = version;
this.localPath = localPath;
this.deployPath = deployPath;
}
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getLocalPath() {
return localPath;
}
public void setLocalPath(String localPath) {
this.localPath = localPath;
}
public String getDeployPath() {
return deployPath;
}
public void setDeployPath(String deployPath) {
this.deployPath = deployPath;
}
@Override
public String toString() {
return "ProjectInfo{" +
"projectName='" + projectName + '\'' +
", version='" + version + '\'' +
", localPath='" + localPath + '\'' +
", deployPath='" + deployPath + '\'' +
'}';
}
}
ServerInfo:服务器信息
/
* 服务器信息
*
* @author lzlg
*/
public class ServerInfo {
/
* 主机ip
*/
private String ip;
/
* 主机tcp端口
*/
private int port;
/
* 主机root用户
*/
private String root;
/
* 主机root用户密码
*/
private String password;
private ServerInfo(String ip, int port, String root, String password) {
this.ip = ip;
this.port = port;
this.root = root;
this.password = password;
}
public ServerInfo(String ip, String root, String password) {
this(ip, 22, root, password);
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getRoot() {
return root;
}
public void setRoot(String root) {
this.root = root;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "ServerInfo{" +
"ip='" + ip + '\'' +
", port=" + port +
", root='" + root + '\'' +
", password='" + password + '\'' +
'}';
}
}
工厂类:
/
* 项目发布信息工厂类
*
* @author lzlg
*/
public class InfoFactory {
private InfoFactory() {
}
/
* 项目信息
*/
private static ProjectInfo projectInfo;
/
* 服务器信息
*/
private static ServerInfo serverInfo;
/
* 设置服务器信息
*/
public static void setServerInfo(String ip, String root, String password) {
if (ObjectUtils.isEmpty(ip)) {
throw new NullPointerException("IP can not be null.");
}
if (ObjectUtils.isEmpty(root)) {
throw new NullPointerException("User name can not be null.");
}
if (ObjectUtils.isEmpty(password)) {
throw new NullPointerException("Password can not be null.");
}
serverInfo = new ServerInfo(ip, root, password);
CheckUtils.check(serverInfo);
}
/
* 设置项目信息
*/
public static void setProjectInfo(String projectName, String version, String localPath) {
String deployPath = "/root/" + projectName;
setProjectInfo(projectName, version, localPath, deployPath);
}
/
* 设置项目信息
*/
private static void setProjectInfo(String projectName, String version, String localPath, String deployPath) {
if (ObjectUtils.isEmpty(projectName)) {
throw new NullPointerException("Project name can not be null.");
}
if (ObjectUtils.isEmpty(version)) {
throw new NullPointerException("Project version can not be null.");
}
if (ObjectUtils.isEmpty(localPath)) {
throw new NullPointerException("Project local path can not be null.");
}
if (ObjectUtils.isEmpty(deployPath)) {
throw new NullPointerException("Deploy path can not be null.");
}
projectInfo = new ProjectInfo(projectName, version, localPath, deployPath);
CheckUtils.check(projectInfo);
}
/
* 获取项目信息
*/
public static ProjectInfo getProjectInfo() {
if (ObjectUtils.isEmpty(projectInfo)) {
throw new NullPointerException("Project info can not be null.");
}
return projectInfo;
}
/
* 获取服务器信息
*/
public static ServerInfo getServerInfo() {
if (ObjectUtils.isEmpty(serverInfo)) {
throw new NullPointerException("Server info can not be null.");
}
return serverInfo;
}
}
工具类:
/
* 检查参数是否符合规范的工具类
*
* @author lzlg
*/
public class CheckUtils {
private CheckUtils() {
}
private static final String ip_pattern = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\."
+ "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
+ "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
+ "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$";
private static final String linux_path_pattern = "^~?[A-Za-z0-9_/]*$";
private static final String windows_path_pattern = "^[A-Za-z]+:[/|\\\\][A-Za-z0-9_/|\\\\]*$";
private static final String project_name_pattern = "^([A-Za-z0-9_]+-*)+$";
private static final String version_pattern = "^\\d+\\.\\d+\\.\\d+$";
/
* 检查服务器信息是否符合规范
*/
public static void check(ServerInfo serverInfo) {
String ip = serverInfo.getIp();
boolean matchIp = ip.matches(ip_pattern);
if (!matchIp) {
throw new InvalidParameterException("IP in server info is invalid.");
}
if (serverInfo.getPort() != 22) {
throw new InvalidParameterException("Port in server info is invalid.");
}
}
/
* 检查项目信息是否符合规范
*/
public static void check(ProjectInfo projectInfo) {
if (!projectInfo.getProjectName().matches(project_name_pattern)) {
throw new InvalidParameterException("Project name in project info is invalid.");
}
if (!projectInfo.getVersion().matches(version_pattern)) {
throw new InvalidParameterException("Project version in project info is invalid.");
}
if (!projectInfo.getLocalPath().matches(windows_path_pattern)) {
throw new InvalidParameterException("Project local path in project info is invalid.");
}
if (!projectInfo.getDeployPath().matches(linux_path_pattern)) {
throw new InvalidParameterException("Deploy path in project info is invalid.");
}
}
}
/
* 命令生成工具类
*
* @author lzlg
*/
public class CMDStatementUtils {
private CMDStatementUtils() {
}
/
* 运行项目命令
*/
public static String getRunStatement() {
ProjectInfo projectInfo = InfoFactory.getProjectInfo();
return changeDir(projectInfo.getDeployPath()) + " && " +
runJar(projectInfo.getProjectName(), projectInfo.getVersion());
}
/
* 获取项目的进程ID
*/
public static String getPID() {
ProjectInfo projectInfo = InfoFactory.getProjectInfo();
return getPID(projectInfo.getProjectName());
}
/
* 杀死指定项目的进程
*/
public static String killProcess(String pid) {
return "kill -9 " + pid;
}
/
* windows环境下调用maven命令
*/
public static String mvn() {
ProjectInfo projectInfo = InfoFactory.getProjectInfo();
return mvn(projectInfo.getLocalPath());
}
/
* 查看日志运行情况命令
*/
public static String tail() {
ProjectInfo projectInfo = InfoFactory.getProjectInfo();
return tail(projectInfo.getProjectName());
}
/
* 创建目录
*/
public static String mkdir() {
ProjectInfo projectInfo = InfoFactory.getProjectInfo();
return mkdir(projectInfo.getDeployPath());
}
/
* 改变目录
*/
public static String changeDir() {
ProjectInfo projectInfo = InfoFactory.getProjectInfo();
return changeDir(projectInfo.getDeployPath());
}
/
* 创建目录
*/
private static String mkdir(String absolutePath) {
return "mkdir " + absolutePath;
}
/
* windows环境下调用maven命令
*/
private static String mvn(String localPath) {
return "cmd /c mvn clean package -f " + localPath;
}
/
* jar包的部署命令
* nohup java -jar myblog-1.0.0.jar > myblog.log &
*/
private static String runJar(String projectName, String version) {
return "nohup java -jar " + projectName + "-" + version + ".jar > " + projectName + ".log &";
}
/
* 发布项目前清理旧项目以前的jar包
*/
private static String clearJar(String projectName, String version) {
return "rm -f " + projectName + "-" + version + ".jar";
}
/
* 发布项目前清理旧项目实时的日志
*/
private static String clearRunLog(String projectName) {
return "rm -f " + projectName + ".log";
}
/
* 改变目录
*/
private static String changeDir(String deployPath) {
return "cd " + deployPath;
}
/
* 获取pid命令
*/
private static String getPID(String processName) {
return "ps -ef | grep " + processName + " | grep -v grep | awk '{print $2}'";
}
/
* 查看运行日志命令
*/
private static String tail(String projectName) {
return "tail -f " + projectName + ".log";
}
}
/
* 命令执行工具类
*
* @author lzlg
*/
public class CMDExecuteUtils {
private CMDExecuteUtils() {
}
/
* 执行杀死进程
*/
public static void kill() {
String command = CMDStatementUtils.getPID();
String pid = SCPUtils.executeGetResult(command);
if (!ObjectUtils.isEmpty(pid)) {
SCPUtils.execute(CMDStatementUtils.killProcess(pid));
}
}
/
* 运行项目
*/
public static void run() {
String command = CMDStatementUtils.getRunStatement();
SCPUtils.executeShell(command);
}
}
/
* SCP上传工具类
*
* @author lzlg
*/
public class SCPUtils {
private SCPUtils() {
}
private static Logger logger = LoggerFactory.getLogger(SCPUtils.class);
private static Connection connection;
/
* 暴露给外部使用的上传文件方法
*/
public static void upload() {
ProjectInfo projectInfo = InfoFactory.getProjectInfo();
ServerInfo serverInfo = InfoFactory.getServerInfo();
String localPath = projectInfo.getLocalPath();
String projectName = projectInfo.getProjectName();
String version = projectInfo.getVersion();
String localFilePath = localPath + File.separator + "target" + File.separator + projectName + "-" + version + ".jar";
logger.info("The uploaded file is " + localFilePath);
upload(serverInfo.getIp(), serverInfo.getPort(), localFilePath,
serverInfo.getRoot(), serverInfo.getPassword(), projectInfo.getDeployPath());
}
/
* 暴露给外部使用的执行Linux命令的方法
*/
public static void execute(String command) {
ServerInfo serverInfo = InfoFactory.getServerInfo();
execute(serverInfo.getIp(), serverInfo.getPort(), serverInfo.getRoot(), serverInfo.getPassword(), command);
}
/
* 暴露给外部使用的执行Linux命令的方法
*/
public static String executeGetResult(String command) {
ServerInfo serverInfo = InfoFactory.getServerInfo();
return executeGetResult(serverInfo.getIp(), serverInfo.getPort(), serverInfo.getRoot(), serverInfo.getPassword(), command);
}
/
* 暴露给外部使用的执行Linux命令的方法
*/
public static void executeShell(String command) {
ServerInfo serverInfo = InfoFactory.getServerInfo();
executeShell(serverInfo.getIp(), serverInfo.getPort(), serverInfo.getRoot(), serverInfo.getPassword(), command);
}
/
* 获取Server服务器连接
*/
private static Connection getConnection(String ip, int port, String root, String password) {
if (ObjectUtils.isEmpty(connection)) {
connection = new Connection(ip, port);
logger.info("Start connect remote server...");
try {
connection.connect();
boolean isAuthenticated = connection.authenticateWithPassword(root, password);
if (!isAuthenticated) {
logger.info("Can not connect remote server...");
throw new RuntimeException();
}
return connection;
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
} else {
return connection;
}
}
/
* 关闭链接
*/
public static void closeConnection() {
connection.close();
}
/
* 上传文件到服务器
*/
private static void upload(String ip, int port, String localFilePath, String root, String password, String remotePath) {
logger.info("ip is " + ip + ", port is " + port + ", root is " + root + ", password is " + password
+ "; Upload " + localFilePath + " to " + remotePath + ".");
File f = new File(localFilePath);
if (!f.exists()) {
throw new RuntimeException("The uploaded file is not found.");
}
execute(CMDStatementUtils.mkdir());
Connection connection = getConnection(ip, port, root, password);
try {
SCPClient scpClient = new SCPClient(connection);
SCPOutputStream os = scpClient.put(f.getName(), f.length(), remotePath, null);
byte[] b = new byte[4096];
FileInputStream fis = new FileInputStream(f);
int i;
logger.info("Start upload file to remote server...");
while ((i = fis.read(b)) != -1) {
os.write(b, 0, i);
}
os.flush();
fis.close();
os.close();
logger.info("Finish upload file...");
} catch (IOException e) {
e.printStackTrace();
logger.info("There are exceptions in uploading : " + e.getMessage());
}
}
private static Session session;
/
* 在服务器中执行shell命令
*/
private static void execute(String ip, int port, String root, String password, String command) {
try {
Connection connection = getConnection(ip, port, root, password);
session = connection.openSession();
session.execCommand(command);
} catch (IOException e) {
e.printStackTrace();
}
}
/
* 在服务器中执行shell命令
*/
private static void executeShell(String ip, int port, String root, String password, String command) {
try {
Connection connection = getConnection(ip, port, root, password);
session = connection.openSession();
session.requestPTY("bash");
session.startShell();
PrintWriter out = new PrintWriter(session.getStdin());
out.println(command);
out.println("exit");
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/
* 在服务器中执行shell命令
*/
private static String executeGetResult(String ip, int port, String root, String password, String command) {
execute(ip, port, root, password, command);
String result = getStdout(session.getStdout());
logger.info("Stout is " + result);
return result;
}
/
* 获取执行shell命令后的控制台输出
*/
private static String getStdout(InputStream in) {
InputStream stdout = new StreamGobbler(in);
StringBuilder builder = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(stdout, StandardCharsets.UTF_8));
String line;
while ((line = br.readLine()) != null) {
builder.append(line).append("\n");
}
} catch (IOException e) {
logger.error("Parsing case exception : " + e.getMessage());
e.printStackTrace();
}
return builder.toString();
}
}
/
* 对象工具类
*
* @author lzlg
*/
public class ObjectUtils {
private ObjectUtils() {
}
/
* 验证对象是否为空,从spring中copy过来的
*/
public static boolean isEmpty(Object obj) {
if (obj == null) {
return true;
} else if (obj instanceof CharSequence) {
return ((CharSequence) obj).length() == 0;
} else if (obj.getClass().isArray()) {
return Array.getLength(obj) == 0;
} else if (obj instanceof Collection) {
return ((Collection) obj).isEmpty();
} else {
return obj instanceof Map && ((Map) obj).isEmpty();
}
}
}
发布项目接口:
/
* 发布项目接口
*
* @author lzlg
*/
public interface PublishProject {
/
* 发布项目
*/
void publish();
}
发布项目抽象类:
/
* 发布抽象类,用于定义发布的基础流程
*
* @author lzlg
*/
public abstract class AbstractPublishProject implements PublishProject {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private final Runtime runtime = Runtime.getRuntime();
@Override
public void publish() {
logger.info("Start publish project...");
// 1.调用maven命令clean package
mavenProject();
// 2.上传打包后的war或jar包到Linux服务器上
uploadToServer();
// 3.服务器运行命令,项目运行
runProject();
logger.info("Finish publish project...");
}
/
* 调用maven命令clean package
*/
private void mavenProject() {
logger.info("Command mvn clean package...");
String command = CMDStatementUtils.mvn();
try {
Process exec = runtime.exec(command);
while (exec.isAlive()) {
}
} catch (IOException e) {
e.printStackTrace();
}
}
/
* 上传项目到指定路径
*/
private void uploadToServer() {
logger.info("Upload packaged project to server...");
SCPUtils.upload();
}
/
* 服务器运行命令,项目运行
*/
private void runProject() {
// 1.杀死原来的项目进程
CMDExecuteUtils.kill();
// 2.运行命令
CMDExecuteUtils.run();
}
}
默认发布项目类:
/
* 默认发布项目接口的实现
*
* @author lzlg
*/
public class DefaultPublishProject extends AbstractPublishProject {
}
执行入口:
public class PublishMain {
public static void main(String[] args) {
InfoFactory.setServerInfo(yourServerIp, yourServerRoot, yourServerPassword);
InfoFactory.setProjectInfo(projectName, version, localPath);
PublishProject publishProject = new DefaultPublishProject();
publishProject.publish();
}
}