Remote execute command in Java example

English 简体中文 繁体中文 ภาษาไทย Tiếng Việt
Summary

When needing to programmatically execute commands on remote systems from a Java application, the JSch library provides a pure Java implementation of SSH2 for this purpose. Developers can establish secure SSH connections, open an "exec" channel, and send commands to a remote server without direct login. The output from these commands is then captured by reading the channel's input stream, enabling automated task execution and centralized result collection, especially useful in distributed environments. The process involves creating a JSch session, configuring connection properties, setting credentials, and managing channel and session lifecycles. Beyond command execution, JSch also supports features like port forwarding and file transfer.

经常需要登录远程系统并运行一些命令或程序以获取输出,许多软件都可以实现此目的,例如putty和gitshell。这些软件通常提供对远程系统的安全访问。但是,您是否想过,如果您需要同时在许多不同的系统上运行命令并将所有这些结果返回到一个地方,该怎么办?尤其在大数据时代,许多任务可能在不同的分布式系统上运行,而您希望有一个单一的地方来累积结果。

在这篇文章中,我们将介绍一个可以帮助实现此目标的Java库——JSch。它是SSH2的纯Java实现。JSch允许您连接到sshd服务器并使用端口转发、X11转发、文件传输等,您可以将其功能集成到您自己的Java程序中。

使用它的好处是您可以通过编程方式连接到远程服务器并在那里执行一些命令,而无需实际登录到它。下面是一个如何在远程Linux服务器上运行ls -la的示例。

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();
		}
	}
}

运行程序后,输出为:

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

这非常方便。如果您想在两个远程系统上运行相同的命令,您只需要创建一个新的会话和通道并执行相同的操作。

JSch可以帮助做更多的事情,包括端口转发、文件传输等。

JSCH EXAMPLE DISTRIBUTED SYSTEM SSH2

  RELATED

  COMMENTS

11
Anonymous
Aug 6, 2017 at 11:10 pm

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?

Ke Pi
Aug 7, 2017 at 9:03 am

Apparently the error you are seeing is that remote end refuses the connection. Maybe the port is not accessible. Please make sure that you can telnet to the remote host at port 22.

Anonymous
May 14, 2018 at 4:30 am

Hi Sonic,

on a Windows server how can I connect? I can't use 22 port.

Thanks,

Sara

Ke Pi
May 14, 2018 at 10:00 am

What do you mean by you cannot use port 22? The port you should use depends on what port the SSHd service is listening at the other end. 

Venni
Aug 14, 2018 at 9:04 am

How can we execute multiple commands ?

Ke Pi
Aug 14, 2018 at 10:58 am

Can try to delimit the command with semicolon

Anonymous
Dec 9, 2019 at 4:01 am

After sending a command I get a prompt where I need to provide an user input. How can I do this?

Ke Pi
Dec 10, 2019 at 9:08 am

Ideally it should not prompt as you already put username. Out of curiosity, what prompt do you see? In your Java output?

Anonymous
Dec 10, 2019 at 10:05 am

It’s like an incident number where i need to give user input

Ke Pi
Dec 11, 2019 at 8:14 am

Maybe it's related to interactive mode of ssh? https://unix.stackexchange.com/questions/349425/ssh-command-and-non-interactive-non-login-shell

Prasun
Jun 7, 2020 at 2:56 am

i'm new to java.. just trying to creating ssh connection and execute the shell script which has pretty long output in console. How can we have handle such scenario. I see script code is getting hanged and not display the console output.