JSch - Java Secure Channel

Apr 20, 2016



http://www.jcraft.com/jsch

JSch는 SSH2를 구현한 Java 라이브러리다. 이 라이브러리를 통해 Java에서 SSH 서버에 접속할 수 있고 포트 포워딩이나 파일 전송, 리모트 명령 수행이 가능하다.

Remote Command Example

개인 프로젝트에서 SSH로 리모트 명령을 수행하는게 필요하여 간단한 테스트 코드를 작성해보았다. 아래 코드에서는 set -e , date, sleep 5 , whoami 를 순차적으로 실행하고 로그로 출력한다. 첫 명령어로 set -e 를 준 이유는 오류 발생시 이 후의 명령이 실행되는 것을 중단하기 위함이다.

  • pom.xml
<dependency>
	<groupId>com.jcraft</groupId>
	<artifactId>jsch</artifactId>
	<version>0.1.53</version>
</dependency>
  • SshShellTaskTest.java
package com.inter6.server.task;

import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.junit.Test;

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * Created by inter6 on 2015. 8. 23..
 */
@Slf4j
public class SshShellTaskTest {

	@Test
	public void execTest() throws Exception {
		Session session = null;
		try {
			session = new JSch().getSession("USERNAME", "IP", PORT);
			session.setPassword("PASSWORD");
			session.setUserInfo(new SshUserInfo());
			session.connect(3 * 1000);

			ChannelExec channel = null;
			try {
				channel = (ChannelExec) session.openChannel("exec");
				channel.setCommand("set -e\ndate\nsleep 5\nwhoami");
				channel.connect(3 * 1000);
				consumeExecOutput(channel);
			} finally {
				if (channel != null) {
					channel.disconnect();
				}
			}
		} finally {
			if (session != null) {
				session.disconnect();
			}
		}
	}

	private void consumeExecOutput(final ChannelExec channel) throws InterruptedException {
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					BufferedReader reader = IOUtils.toBufferedReader(new InputStreamReader(channel.getInputStream(), "UTF-8"));
					while (channel.isConnected()) {
						String outputMsg = reader.readLine();
						if (outputMsg == null) {
							outputMsg = "[disconnected]";
						}
						log.info(outputMsg);
						Thread.sleep(1000);
					}
				} catch (Throwable e) {
					log.error("execute fail !", e);
				}
			}
		}).start();

		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					BufferedReader reader = IOUtils.toBufferedReader(new InputStreamReader(channel.getErrStream(), "UTF-8"));
					while (channel.isConnected()) {
						String outputMsg = reader.readLine();
						if (outputMsg == null) {
							outputMsg = "[disconnected]";
						}
						log.error(outputMsg);
						Thread.sleep(1000);
					}
				} catch (Throwable e) {
					log.error("execute fail !", e);
				}
			}
		}).start();

		while (channel.isConnected()) {
			Thread.sleep(10 * 1000);
		}
	}

	private class SshUserInfo implements UserInfo {

		@Override
		public String getPassphrase() {
			return null;
		}

		@Override
		public String getPassword() {
			return null;
		}

		@Override
		public boolean promptPassword(String message) {
			return false;
		}

		@Override
		public boolean promptPassphrase(String message) {
			return false;
		}

		@Override
		public boolean promptYesNo(String message) {
			return true;
		}

		@Override
		public void showMessage(String message) {

		}
	}
}