Frequently there is a need to logon to a remote system and run some commands or programs to get the output, many software can serve this purpose such as putty and gitshell.These software usually provide secure access to the remote system. But have you ever wondered what to do if you need to run commands on many different systems at the same time and get all these results back at a single place? Especially in big data era, many tasks may run on different distributed systems and you want o have a single place to accumulate the result.
In this post, we will introduce a Java library which can help achieve this -- JSch. It is a pure Java implementation of SSH2. JSch allows you to connect to an sshd server and use port forwarding, X11 forwarding, file transfer, etc., and you can integrate its functionality into your own Java programs.
The benefit of using it is that you can programmablly connect to the remove server and execute some commands there without actually login to it. Below is an example on how you can run ls -la on a remote Linux server.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Properties; import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelExec; import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; public class JSchTest { public static void main(String[] args){ try{ String command = "ls -la"; String host = "host_ip"; String user = "username"; String password = "password"; JSch jsch = new JSch(); Session session = jsch.getSession(user, host, 22); Properties config = new Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config);; session.setPassword(password); session.connect(); Channel channel = session.openChannel("exec"); ((ChannelExec)channel).setCommand(command); channel.setInputStream(null); ((ChannelExec)channel).setErrStream(System.err); InputStream input = channel.getInputStream(); channel.connect(); System.out.println("Channel Connected to machine " + host + " server with command: " + command ); try{ InputStreamReader inputReader = new InputStreamReader(input); BufferedReader bufferedReader = new BufferedReader(inputReader); String line = null; while((line = bufferedReader.readLine()) != null){ System.out.println(line); } bufferedReader.close(); inputReader.close(); }catch(IOException ex){ ex.printStackTrace(); } channel.disconnect(); session.disconnect(); }catch(Exception ex){ ex.printStackTrace(); } } }
After running the program, the output is :
Channel Connected to machine hostname server with command: ls -la total 1367872 drwxr-xr-x 33 peter users 4096 Dec 11 16:49 . drwxr-xr-x 6 root root 4096 Mar 21 2014 .. -rw------- 1 peter users 15607 Dec 11 19:01 .bash_history -rw-r--r-- 1 peter users 1177 Mar 21 2014 .bashrc drwxr-xr-x 2 peter users 4096 Sep 12 09:47 bin drwxrwxrwx 2 peter users 4096 Sep 3 14:10 cfg
It's pretty convenient. If you want to run the same command on two remote systems, you just need to create a new session and channel and do the same.
JSch can help do a lot more including port forwarding, file transfer etc.
Hey Sonic,
Great article. That is what i was looking for. Thanks
But i am getting a "com.jcraft.jsch.JSchException: java.net.ConnectException: Connection refused: connect" error.
Any insights here?