mina-sshd/mina-sftp实现远程执行ssh命令或文件上传
场景&需求
- 系统需要时不时向一台远程主机发送ssh命令,并且需要上传文件
- 希望可以像使用数据库一样使用ssh(配置化)
- 不希望发送一次命令创建一个连接,能实现ssh连接池
- 不使用ganymed-ssh2或jsch,因为这两个工具年代久远,活跃度较低,出现问题解决困难
- apache mina-ssh活跃度很高,但是工具较新,文档不是很完善
选型
最后选择了apache mina-ssh,一是社区活跃度较高,另外依托于apache mina,性能可以保障,并且mina生态下还有sftp/http/git/scp等工具,让系统有更多的可能性。
代码
使用方法
ssh
public class SshTest {
public static void main(String[] args) throws Exception {
// ssh client
SshClient client = ClientBuilder.builder().build();
CoreModuleProperties.IDLE_TIMEOUT.set(client, Duration.ZERO);
client.start();
// ssh config
SshConfig sshConfig = new SshConfig();
sshConfig.setIp("127.0.0.1");
sshConfig.setAuthType("PASSWORD");
sshConfig.setPort(22);
sshConfig.setUsername("root");
sshConfig.setPassword("root");
// ssh connection factory
SshConnectionFactory sshConnectionFactory = new SshConnectionFactory(sshConfig, client);
// ssh connection pool
GenericObjectPoolConfig<ClientSession> config = new GenericObjectPoolConfig<>();
config.setMaxIdle(sshConfig.getMaxIdle());
config.setMaxTotal(sshConfig.getMaxTotal());
config.setMinIdle(sshConfig.getMinIdle());
config.setTestWhileIdle(sshConfig.getTestWhileIdle());
config.setTestOnCreate(sshConfig.getTestOnCreate());
config.setTestOnBorrow(sshConfig.getTestOnBorrow());
config.setTestOnReturn(sshConfig.getTestOnReturn());
config.setMinEvictableIdleTimeMillis(sshConfig.getMinEvictableIdleTimeMillis());
config.setTimeBetweenEvictionRunsMillis(sshConfig.getTimeBetweenEvictionRunsMillis());
config.setBlockWhenExhausted(sshConfig.getBlockWhenExhausted());
config.setMaxWaitMillis(sshConfig.getMaxWaitMillis());
config.setJmxEnabled(false);
AbandonedConfig abandonedConfig = new AbandonedConfig();
abandonedConfig.setLogAbandoned(true);
SshConnectionPool sshConnectionPool = new SshConnectionPool(sshConnectionFactory, config, abandonedConfig);
SshExecutor sshExecutor = new SshExecutor(sshConnectionPool, sshConfig);
Scanner scanner = new Scanner(System.in);
String line;
while (true) {
line = scanner.nextLine();
if (StringUtils.isNotBlank(line) && !line.equalsIgnoreCase("exit")) {
System.out.println(sshExecutor.exec(line));
} else {
sshConnectionPool.close();
client.close();
break;
}
}
}
}
sftp
public class SftpTest {
public static void main(String[] args) throws Exception {
// ssh client
SshClient client = ClientBuilder.builder().build();
CoreModuleProperties.IDLE_TIMEOUT.set(client, Duration.ZERO);
client.start();
// ssh config
SshConfig sshConfig = new SshConfig();
sshConfig.setIp("127.0.0.1");
sshConfig.setAuthType("PASSWORD");
sshConfig.setPort(22);
sshConfig.setUsername("root");
sshConfig.setPassword("root");
// ssh connection factory
SshConnectionFactory sshConnectionFactory = new SshConnectionFactory(sshConfig, client);
// ssh connection pool
GenericObjectPoolConfig<ClientSession> config = new GenericObjectPoolConfig<>();
config.setMaxIdle(sshConfig.getMaxIdle());
config.setMaxTotal(sshConfig.getMaxTotal());
config.setMinIdle(sshConfig.getMinIdle());
config.setTestWhileIdle(sshConfig.getTestWhileIdle());
config.setTestOnCreate(sshConfig.getTestOnCreate());
config.setTestOnBorrow(sshConfig.getTestOnBorrow());
config.setTestOnReturn(sshConfig.getTestOnReturn());
config.setMinEvictableIdleTimeMillis(sshConfig.getMinEvictableIdleTimeMillis());
config.setTimeBetweenEvictionRunsMillis(sshConfig.getTimeBetweenEvictionRunsMillis());
config.setBlockWhenExhausted(sshConfig.getBlockWhenExhausted());
config.setMaxWaitMillis(sshConfig.getMaxWaitMillis());
config.setJmxEnabled(false);
AbandonedConfig abandonedConfig = new AbandonedConfig();
abandonedConfig.setLogAbandoned(true);
SshConnectionPool sshConnectionPool = new SshConnectionPool(sshConnectionFactory, config, abandonedConfig);
SshExecutor sshExecutor = new SshExecutor(sshConnectionPool, sshConfig);
Scanner scanner = new Scanner(System.in);
String line;
while (true) {
line = scanner.nextLine();
if (StringUtils.isNotBlank(line) && !line.equalsIgnoreCase("exit")) {
File file = new File(line);
if (file.exists() && file.isFile()) {
sshExecutor.upload("/tmp", file.getName(), new FileInputStream(file));
} else {
System.err.println("file not exists: " + line);
}
} else {
sshConnectionPool.close();
client.close();
break;
}
}
}
}