原创

自己写的发布小工具


自己写的发布小工具

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();
    }
}
发布项目
小工具
  • 作者:lzlg520
  • 发表时间:2019-12-14 17:51
  • 版权声明:自由转载-非商用-非衍生-保持署名
  • 公众号转载:请在文末添加作者公众号二维码