JAVA代码实现SSH连接执行Linux命令实现增量发布

分类: Linux 评论(8) 974 阅读 2018-02-02 09:47 ZooM查看

摘要 JAVA代码实现SSH连接执行Linux命令 实现增量更新并重启Tomcat服务器
Linux Tomcat


  突发奇想,想用JAVA代码实现执行Linux脚本,实现 增量文件的上传然后重启Tomcat服务器. 经百度后发现了可行的方式.


  1: 需要借助于 ganymed-ssh2-build210.jar jar

  2: 默认一次只能执行一个命令(不然会抛出A remote execution has already started.) 要想实现执行多个命令 需要执行多次 或者 写成批文件的形式 再或者 几条命令合并成为一条语句执行

package ssh;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;

public class Scpclient {
	
	// IP
	private String ip;
	// 端口
	private int port;
	// 用户名
	private String username;
	// 密码
	private String password;
	// 实例
	static private Scpclient instance;
	
	static synchronized public Scpclient getInstance(String IP, int port, String username, String passward) {
		if (instance == null) {
			instance = new Scpclient(IP, port, username, passward);
		}
		return instance;
	}
	
	public Scpclient(String IP, int port, String username, String passward) {
		this.ip = IP;
		this.port = port;
		this.username = username;
		this.password = passward;
	}
	
	public void getFile(String remoteFile, String localTargetDirectory) {
		Connection conn = null;
		try {
			conn = new Connection(ip, port);
			conn.connect();
			boolean isAuthenticated = conn.authenticateWithPassword(username, password);
			if (isAuthenticated == false) {
				System.err.println("authentication failed");
			}
			SCPClient client = new SCPClient(conn);
			client.get(remoteFile, localTargetDirectory);
			conn.close();
		} catch (IOException ex) {
			Logger.getLogger(SCPClient.class.getName()).log(Level.SEVERE, null, ex);
		}finally {
			if (conn != null) conn.close();
		}
	}
	
	public void putFile(String localFile, String remoteTargetDirectory) {
		Connection conn = null;
		try {
			conn = new Connection(ip, port);
			conn.connect();
			boolean isAuthenticated = conn.authenticateWithPassword(username, password);
			if (isAuthenticated == false) {
				System.err.println("authentication failed");
			}
			SCPClient client = new SCPClient(conn);
			client.put(localFile, remoteTargetDirectory);
			conn.close();
		} catch (IOException ex) {
			Logger.getLogger(SCPClient.class.getName()).log(Level.SEVERE, null, ex);
		}finally {
			if (conn != null) conn.close();
		}
	}
	
	/**
	 * 上传文件
	 * @param localFile
	 * @param remoteFileName
	 * @param remoteTargetDirectory
	 * @param mode 
	 * Author:YCM 
	 * 2017年12月28日 上午11:12:08
	 */
	public void putFile(String localFile, String remoteFileName, String remoteTargetDirectory, String mode) {
		Connection conn = null;
		Session sess = null;
		try {
			conn = new Connection(ip, port);
			conn.connect();
			// 进行认证
			boolean isAuthenticated = conn.authenticateWithPassword(username, password);
			if (isAuthenticated == false) {
				System.err.println("authentication failed");
			}
			SCPClient client = new SCPClient(conn);
			if ((mode == null) || (mode.length() == 0)) {
				// 默认执行模式
				mode = "0600";
			}
			
			client.put(localFile, remoteFileName, remoteTargetDirectory, mode);
			
			//重命名
			sess = conn.openSession();
			String tmpPathName = remoteTargetDirectory + File.separator + remoteFileName;
			String newPathName = tmpPathName.substring(0, tmpPathName.lastIndexOf("."));
			sess.execCommand("mv " + remoteFileName + " " + newPathName);//重命名回来
			sess.close();
			conn.close();
		} catch (IOException ex) {
			Logger.getLogger(SCPClient.class.getName()).log(Level.SEVERE, null, ex);
		}finally {
			if (sess != null) sess.close();
			if (conn != null) conn.close();
		}
	}
	
	/**
	 * 上传文件,不支持重命名
	 * @param collections
	 * @param serverRootPath
	 * @param zlRootPath
	 * @param mode 
	 * Author:YCM 
	 * 2017年12月28日 上午11:10:49
	 */
	public void putFile(Collection collections,String serverRootPath,String zlRootPath,String mode) {
		Connection conn = null;
		try {
			conn = new Connection(ip, port);
			conn.connect();
			boolean isAuthenticated = conn.authenticateWithPassword(username, password);
			if (isAuthenticated == false) {
				System.err.println("authentication failed");
			}
			SCPClient client = new SCPClient(conn);
			if ((mode == null) || (mode.length() == 0)) {
				mode = "0600";
			}
			
			int index = 1;
			for (File file : collections) {
				// 本地路径
				String diskPath = file.getPath();
				
				System.out.println("......上传增量文件[" + index + "][" + diskPath + "]");
				// 相对路径
				String relativePath = diskPath.replace(zlRootPath, "").replace("\\", "/");
				relativePath = relativePath.substring(0, relativePath.lastIndexOf("/"));
				
				// 文件名称
				String fileName = file.getName();
				// 上传文件
				client.put(diskPath, fileName, serverRootPath + relativePath, mode);
				index++;
			}
			conn.close();
		} catch (IOException ex) {
			Logger.getLogger(SCPClient.class.getName()).log(Level.SEVERE, null, ex);
		}finally {
			if (conn != null) conn.close();
		}
	}
	
	/**
	 * 创建文件夹
	 */
	public void createFolder(Collection collections) {
		Connection conn = null;
		Session sess = null;
		try {
			conn = new Connection(ip, port);
			conn.connect();
			boolean isAuthenticated = conn.authenticateWithPassword(username, password);
			if (isAuthenticated == false) {
				System.err.println("authentication failed");
			}
			sess = conn.openSession();
			// 不能执行多次命令,一次只能执行一条命令(不然会抛出A remote execution has already started.)
			String command = "mkdir -p ";
			for (String remoteTargetDirectory : collections) {
				if (remoteTargetDirectory.contains(".")) {
					String folderPath = remoteTargetDirectory.substring(0, remoteTargetDirectory.lastIndexOf("/"));
					command += folderPath + " ";
				}
			}
			sess.execCommand(command);
			sess.close();
			conn.close();
		} catch (IOException ex) {
			Logger.getLogger(SCPClient.class.getName()).log(Level.SEVERE, null, ex);
		}finally {
			if (sess != null) sess.close();
			if (conn != null) conn.close();
		}
	}
	
	public static byte[] getBytes(String filePath) {
		byte[] buffer = null;
		try {
			File file = new File(filePath);
			FileInputStream fis = new FileInputStream(file);
			ByteArrayOutputStream byteArray = new ByteArrayOutputStream(1024 * 1024);
			byte[] b = new byte[1024 * 1024];
			int i;
			while ((i = fis.read(b)) != -1) {
				byteArray.write(b, 0, i);
			}
			fis.close();
			byteArray.close();
			buffer = byteArray.toByteArray();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return buffer;
	}
	
	public void readWell(File file, List filesList) {
		if (file.isDirectory()) {
			File[] listFiles = file.listFiles();
			for (File fle : listFiles) {
				if (fle.isDirectory()) {
					readWell(fle, filesList);
				} else {
					filesList.add(fle);
				}
			}
		} else {
			filesList.add(file);
		}
	}
	
	/**
	 * 输出日志
	 */
	public void tailViewTomcatLog(String shell) {
		Connection conn = null;
		Session sess = null;
		try {
			conn = new Connection(ip, port);
			conn.connect();
			boolean isAuthenticated = conn.authenticateWithPassword(username, password);
			if (isAuthenticated == false) {
				System.err.println("authentication failed");
			}
			
			sess = conn.openSession();
			if (shell.contains(".sh")) {
				sess.requestDumbPTY();
				sess.startShell();
				PrintWriter out = new PrintWriter(sess.getStdin());
				out.write(shell);
			}else
				sess.execCommand(shell);
			
			System.err.println("[EXEC RESULT:" + shell + "]");
			
			try (StreamGobbler stdout = new StreamGobbler(sess.getStdout()); 
					BufferedReader br = new BufferedReader(new InputStreamReader(stdout))) {
				while (true) {
					String line = br.readLine();
					if (line == null) break;
//					buffer.append(line);
//					buffer.append(System.getProperty("line.separator"));
					System.out.println(line);
				}
			}
		} catch (IOException ex) {
			Logger.getLogger(SCPClient.class.getName()).log(Level.SEVERE, null, ex);
		} finally {
			if (sess != null) sess.close();
			if (conn != null) conn.close();
		}
	}
	
	public void restartServer(String exeShell) {
		Connection conn = null;
		Session sess = null;
		try {
			Connection connection = new Connection("120.120.120.120");
			connection.connect();
			
			boolean authenticateWithPass = connection.authenticateWithPassword("root", "password");
			if (!authenticateWithPass) { throw new RuntimeException("Authentication failed. Please check hostName, userName and passwd"); }
			Session session = connection.openSession();
			
			session = connection.openSession();
			session.requestDumbPTY();
			session.startShell();
			OutputStream stdins = session.getStdin();
			
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(stdins));
			bw.write(exeShell + " \n\r");
			bw.flush();
		} catch (IOException ex) {
			Logger.getLogger(SCPClient.class.getName()).log(Level.SEVERE, null, ex);
		} finally {
			if (sess != null) sess.close();
			if (conn != null) conn.close();
		}
	}
	
	public void exeHander() {
		
	}
	
	public String getUsername() {
		return username;
	}
	
	public void setUsername(String username) {
		this.username = username;
	}
	
	public String getPassword() {
		return password;
	}
	
	public void setPassword(String password) {
		this.password = password;
	}
	
	public int getPort() {
		return port;
	}
	
	public void setPort(int port) {
		this.port = port;
	}
	
	public static void main(String[] args) {
		// String zlRootPath = "C:\\Users\\Administrator\\Desktop\\CS_20171227\\wechat\\ROOT";
		// String wechatServerRootPath = "/mydata/tomcat/wechat/apache-tomcat-8.5.24/webapps/ROOT/";
		
		Scanner in = null;
		try {
			
			System.err.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
			System.err.println("!!!!     注意:增量包需放置在桌面上,并输入增量文件夹名称(大小写忽略)      !!!!");
			System.err.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
			
			in =  new Scanner(System.in);
			
			String zlFolderName = "";
			System.out.print("请输入增量文件夹名称:");
			zlFolderName = in.nextLine();
			
			if (zlFolderName == null || Objects.equals("", zlFolderName.trim())) {
				System.err.println("请输入增量文件夹名称");
				return;
			}
			
			// 转大写
			zlFolderName = zlFolderName.toUpperCase();
			
			System.out.print("请输入将要上传的项目名称:");
			String inProjectName = in.nextLine();
			
			if (inProjectName == null || Objects.equals("", inProjectName.trim())) {
				System.err.println("请输入有效的项目名称");
				return;
			}
			
			String zlRoot = "C:\\Users\\Administrator\\Desktop\\" + zlFolderName,
					serverRoot = "/mydata/tomcat",
					zlRootPath = "",
					serverRootPath = "",
					bashFilePath = "";
			
			switch (inProjectName.trim()) {
			case "admin":
				
				zlRootPath = zlRoot + "\\admin\\ROOT";
				serverRootPath = serverRoot + "/admin/apache-tomcat-8.0.42/webapps/ROOT";
				break;
			case "wechat":
				
				zlRootPath = zlRoot + "\\wechat\\ROOT";
				serverRootPath = serverRoot + "/wechat/apache-tomcat-8.5.24/webapps/ROOT";
				break;
			
			case "core-server":
				
				zlRootPath = zlRoot + "\\core-server\\ROOT";
				serverRootPath = serverRoot + "/core-server/apache-tomcat-8.0.42/webapps/ROOT";
				break;
			default:
				break;
			}

			if (zlRootPath == null || serverRootPath == null || 
				Objects.equals("", zlRootPath) || Objects.equals("", serverRootPath)) {
				System.err.println("请输入有效的项目名称");
				return;
			}
			
			// 可执行文件路径
			bashFilePath = serverRootPath.replace("/webapps/ROOT", "");
			
			// 判断增量文件夹是否存在
			File zlRootFile = new File(zlRootPath);
			if(!zlRootFile.exists()) {
				System.err.println("增量文件夹不存在");
				return;
			}
			
			System.out.println("执行上传Linux脚本[开始]");
			
			Scpclient scp = Scpclient.getInstance("120.120.120.120", 22, "root", "password");
			List filesList = new ArrayList();
			
			// 递归收集文件
			System.out.println("...收集增量文件[开始]");
			
			scp.readWell(zlRootFile, filesList);
			
			System.out.println("...收集增量文件[结束],文件数:" + filesList.size());
			
			System.out.println("...创建不存在文件夹[开始]");
			
			String finalServerRootPath = serverRootPath,finalZlRootPath = zlRootPath;
			Set folderNames = filesList.stream().map(file -> finalServerRootPath + file.getPath().replace(finalZlRootPath, "").replace("\\", "/"))
					.collect(Collectors.toSet());
			scp.createFolder(folderNames);
			
			System.out.println("...创建不存在文件夹[结束]");
			
			System.out.println("...上传增量文件[开始]");
			
			scp.putFile(filesList,serverRootPath,zlRootPath,null);
			
			System.out.println("...上传增量文件[结束]");
			
			System.out.println("执行上传Linux脚本[结束]");
			
			System.out.print("是否执行重启操作[y/n]:");
			String restart = in.nextLine();
			
			if (Objects.equals("y", restart) || Objects.equals("Y", restart)) {
				
				System.out.println("...执行命令重启服务器[开始]");
				
				System.out.println("...另起线程获取服务器实时日志到本地[开始]");
				
				SSHAgent sshAgent = new SSHAgent();
				sshAgent.setExeShell("tail -f " + bashFilePath + "/logs/catalina.out \n\r");
				new Thread(sshAgent).start(); 
				
				TimeUnit.SECONDS.sleep(5);
				System.out.println("......停止[" + inProjectName + "]服务器[开始]");
				
				//scp.tailViewTomcatLog("cd " + bashFilePath + " && bin/shutdown.sh");
				scp.restartServer(bashFilePath + "/bin/shutdown.sh");
				
				System.out.print("...是否执行启动命令[y/n]:");
				String incontinue = in.nextLine();
				
				if (Objects.equals("y", incontinue) || Objects.equals("Y", incontinue)) {
					
					System.out.println("......重启[" + inProjectName + "]服务器[开始]");
					scp.restartServer(bashFilePath + "/bin/startup.sh");
				}
			}
			
			System.out.print("按任意键退出:");
			in.nextLine();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (in != null) in.close();
		}
	}
	
}



QQ联系作者 微信联系作者
评论8
提交评论

关  于

该站属于个人博客,技术架构: JFinal + Beetl + Bootstrap

功能以后会继续完善……

QQ:841359731