1. 程式人生 > >JSch中執行command的兩種方式

JSch中執行command的兩種方式

準備目標登入主機資訊:

public class DestHost {
	private String host = "";
	private String username = "";
	private String password = "";
	private int port = 22;
	private int timeout = 60 * 60 * 1000;
	
	public DestHost(String host, String username, String password){
		this(host, username, password, 22, 60*60*1000);
	}
	
	public DestHost(String host, String username, String password, int timeout){
		this(host, username, password, 22, timeout);
	}

	public DestHost(String host, String username, String password, int port,
			int timeout) {
		super();
		this.host = host;
		this.username = username;
		this.password = password;
		this.port = port;
		this.timeout = timeout;
	}

...
}

SSH工具類:

1.JSch 使用shell執行命令,有兩種方法:

ChannelExec channelExec = (ChannelExec) session.openChannel("exec");//只能執行一條指令(也可執行符合指令)

    一次性執行多條shell的方法:

        1)每個命令之間用;隔開
            說明:各命令的執行給果,不會影響其它命令的執行。換句話說,各個命令都會執行,但不保證每個命令都執行成功。

        2)每個命令之間用&&隔開
            說明:若前面的命令執行成功,才會去執行後面的命令。這樣可以保證所有的命令執行完畢後,執行過程都是成功的。

        3)每個命令之間用||隔開
            說明:||是或的意思,只有前面的命令執行失敗後才去執行下一條命令,直到執行成功一條命令為止。

ChannelShell channelShell = (ChannelShell) session.openChannel("shell");//可執行多條指令 不過需要輸入輸出流

public class SSHUtils {

	private static final String ENCODING = "UTF-8";
	
	public static Session getJSchSession(DestHost destHost) throws JSchException {
		JSch jsch = new JSch();
		  
		Session session = jsch.getSession(destHost.getUsername(), destHost.getHost(), destHost.getPort());
		session.setPassword(destHost.getPassword());
		session.setConfig("StrictHostKeyChecking", "no");//第一次訪問伺服器不用輸入yes
		session.setTimeout(destHost.getTimeout());
		session.connect();
		
		return session;
	}

    public static String execCommandByJSch(Session session, String command, String  resultEncoding) throws IOException,JSchException{
		
//1.預設方式,執行單句命令		
		ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
		InputStream in = channelExec.getInputStream();
		channelExec.setCommand(command);
		channelExec.setErrStream(System.err);
		channelExec.connect();
		String result = IOUtils.toString(in, resultEncoding);
		channelExec.disconnect();
		
		return result;
		
	}

下面就是使用“shell”方式進行的呼叫:

public static String execCommandByShell(Session session)throws IOException,JSchException{
		String result = "";
		
//2.嘗試解決 遠端ssh只能執行一句命令的情況
		ChannelShell channelShell = (ChannelShell) session.openChannel("shell");
		InputStream inputStream = channelShell.getInputStream();//從遠端到達的資料  都能從這個流讀取到
		channelShell.setPty(true);
		channelShell.connect();
		
		OutputStream outputStream = channelShell.getOutputStream();//寫入該流的資料  都將傳送到遠端端
		//使用PrintWriter 就是為了使用println 這個方法
		//好處就是不需要每次手動給字元加\n
		PrintWriter printWriter = new PrintWriter(outputStream);
		printWriter.println("cd /opt/applog/MSISVCServer");
		printWriter.println("ls");
		printWriter.println("exit");//為了結束本次互動
		printWriter.flush();//把緩衝區的資料強行輸出
		
/**
shell管道本身就是互動模式的。要想停止,有兩種方式: 
一、人為的傳送一個exit命令,告訴程式本次互動結束
二、使用位元組流中的available方法,來獲取資料的總大小,然後迴圈去讀。
為了避免阻塞
*/
		byte[] tmp = new byte[1024];
		while(true){
			
			while(inputStream.available() > 0){
				int i = inputStream.read(tmp, 0, 1024);
				if(i < 0) break;
				String s = new String(tmp, 0, i);
				if(s.indexOf("--More--") >= 0){
					outputStream.write((" ").getBytes());
					outputStream.flush();
				}
				System.out.println(s);
			}
			if(channelShell.isClosed()){
				System.out.println("exit-status:"+channelShell.getExitStatus());
				break;
			}
			try{Thread.sleep(1000);}catch(Exception e){}
			
		}
		outputStream.close();
		inputStream.close();
		channelShell.disconnect();
		session.disconnect();
		System.out.println("DONE");
		
		return result;
	}