java使用jsch连接linux

时间:2021-07-12 01:24:04

由于项目需要使用java来linux进行管理,近一番查找,发现第三方jar包 jsch 可以轻松实现对linux的管理,(相关文档及例子请访问官网www.jcraft.com),故引进。

在网上搜索了一些资料参考并修改(资料来源地址一下子找不到了,有发现的请提醒加上),创建一个工具类,可以实现对linux上的基本操作及系统上文件的上传和下载。

代码如下:

/**
* @description 用来创建与 linux 交互的会话,操作文件和执行 操作 命令
* @date: 2016/7/25
* @author: gongtao
*/
public class LinuxConnetionHelper { private static final org.slf4j.Logger log = LoggerFactory.getLogger(LinuxConnetionHelper.class);
private static final int TIME_OUT = 5*60*1000; //设置超时为5分钟
private static final Map<String,Session> cache = new HashMap<>(); //session缓存 public static SessionMonitor sessionMonitor;
/**
* 创建 连接,需手动关闭
* @param host
* @param userName
* @param password
* @param port
* @throws JSchException
*/
public static Session connect(String host,String userName,String password,int port) throws JSchException {
//创建对象
JSch jsch = new JSch();
//创建会话
Session session = jsch.getSession(userName,host, port);
//输入密码
session.setPassword(password);
//配置信息
Properties config = new Properties();
//设置不用检查hostKey
//如果设置成“yes”,ssh就不会自动把计算机的密匙加入“$HOME/.ssh/known_hosts”文件,
//并且一旦计算机的密匙发生了变化,就拒绝连接。
config.setProperty("StrictHostKeyChecking", "no");
// //默认值是 “yes” 此处是由于我们SFTP服务器的DNS解析有问题,则把UseDNS设置为“no”
// config.put("UseDNS", "no");
session.setConfig(config);
//过期时间
session.setTimeout(TIME_OUT);
//建立连接
session.connect(); return session;
} /**
* 创建 连接,无需手动关闭
* @param host
* @param userName
* @param password
* @param port
* @throws JSchException
*/
public static Session longConnect(String host,String userName,String password,int port) throws JSchException {
String key = host + userName + password + port;
Session session = cache.get(key);
if (session == null){
//创建对象
JSch jsch = new JSch();
//创建会话
session = jsch.getSession(userName,host, port);
//输入密码
session.setPassword(password);
//配置信息
Properties config = new Properties();
//设置不用检查hostKey
//如果设置成“yes”,ssh就不会自动把计算机的密匙加入“$HOME/.ssh/known_hosts”文件,
//并且一旦计算机的密匙发生了变化,就拒绝连接。
config.setProperty("StrictHostKeyChecking", "no");
// //默认值是 “yes” 此处是由于我们SFTP服务器的DNS解析有问题,则把UseDNS设置为“no”
// config.put("UseDNS", "no");
session.setConfig(config);
//过期时间
//session.setTimeout(TIME_OUT);
//建立连接,此时会在linux上新建一个进程,timeout 并不会结束进程,只有调用disconnect()才会结束此进程
session.connect();
cache.put(key,session);
}else{
//判断session是否失效
if (testSessionIsDown(key)){
//session is down
//session 失去连接则清除
closeLongSessionByKey(key);
//重新生成session
session = longConnect(host, userName, password, port);
}
}
//创建定时器
createSessionMonitor();
return session;
} /**
* 销毁 session
* @param session
*/
public static void close(Session session){
if (session != null){
session.disconnect();
}
} /**
* 测试session是否失效
* @param key
* @return
*/
public static boolean testSessionIsDown(String key){
Session session = cache.get(key);
if (session == null){
return true;
}
ChannelExec channelExec = null;
try {
channelExec = openChannelExec(session);
channelExec.setCommand("true");
channelExec.connect();
return false;
}catch (Throwable e){
//session is down
return true;
}finally {
if (channelExec != null){
channelExec.disconnect();
}
}
}
/**
* 销毁 session
* @param key
*/
public static synchronized void closeLongSessionByKey(String key){
Session session = cache.get(key);
if (session != null){
session.disconnect();
cache.remove(key);
}
} /**
* 销毁 session
* @param session
*/
public static void closeLongSessionBySession(Session session){
Iterator iterator = cache.keySet().iterator();
while (iterator.hasNext()){
String key = (String)iterator.next();
Session oldSession = cache.get(key);
if (session == oldSession){
session.disconnect();
cache.remove(key);
return;
}
}
}
/**
* 创建一个 sftp 通道并建立连接
* @param session
* @return
* @throws Exception
*/
public static ChannelSftp openChannelSftp(Session session) throws Exception
{
ChannelSftp channelSftp = (ChannelSftp)session.openChannel("sftp");
channelSftp.connect();
return channelSftp;
} /**
* 关闭 sftp 通道
* @param channelSftp
* @throws Exception
*/
public static void closeChannelSftp(ChannelSftp channelSftp)
{
if (channelSftp != null){
channelSftp.disconnect();
}
} /**
* 下载文件
* @param remoteFile
* 远程服务器的文件路径
* @param localPath
* 需要保存文件的本地路径
* @throws IOException
* @throws SftpException
*/
public static void downloadFile(Session session , String remoteFile, String localPath) throws Exception {
ChannelSftp channelSftp = openChannelSftp(session);
try {
String remoteFilePath = remoteFile.substring(0, remoteFile.lastIndexOf("/"));
String remoteFileName = remoteFile.substring(remoteFile.lastIndexOf("/") + 1,remoteFile.length());
if(localPath.charAt(localPath.length() - 1) != '/'){
localPath += '/';
}
File file = new File(localPath + remoteFileName);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
}
OutputStream output = new FileOutputStream(file);
try {
channelSftp.cd(remoteFilePath);
log.info("远程服务器路径:" + remoteFilePath);
log.info("本地下载路径:" + localPath + remoteFileName);
SftpATTRS attrs = channelSftp.lstat(remoteFile);
channelSftp.get(remoteFile, output, new FileSftpProgressMonitor(attrs.getSize()));
}catch (Exception e){
throw e;
}finally {
output.flush();
output.close();
}
}catch (Exception e){
throw e;
}finally {
closeChannelSftp(channelSftp);
}
} /**
* 上传文件
* @param localFile
* 本地文件路径
* @param remotePath
* 远程服务器路径
* @throws IOException
* @throws SftpException
*/
public static void uploadFile(Session session,String localFile,String remotePath) throws Exception {
ChannelSftp channelSftp = openChannelSftp(session);
String remoteFileName = localFile.substring(localFile.lastIndexOf("/") + 1, localFile.length());
File file = new File(localFile);
final InputStream input = new FileInputStream(file);
try {
channelSftp.cd(remotePath);
}catch (SftpException e){
String tempPath = null;
try {
tempPath = remotePath.substring(0, remotePath.lastIndexOf("/"));
channelSftp.cd(tempPath);
}catch (SftpException e1){
channelSftp.mkdir(tempPath);
}
channelSftp.mkdir(remotePath);
channelSftp.cd(remotePath);
}
log.info("远程服务器路径:" + remotePath);
log.info("本地上传路径:" + localFile);
try {
channelSftp.put(input, remoteFileName, new FileSftpProgressMonitor(file.length()));
}catch (Exception e){
throw e;
}finally {
input.close();
closeChannelSftp(channelSftp);
}
} /**
* 文件上传
* @param session
* @param inputStream
* @param fileName
* @param remotePath
* @throws Exception
*/
public static void uploadFile(Session session,InputStream inputStream,String fileName,String remotePath) throws Exception {
ChannelSftp channelSftp = openChannelSftp(session);
channelSftp.cd(remotePath);
log.info("远程服务器路径:" + remotePath);
try {
channelSftp.put(inputStream, fileName,new FileSftpProgressMonitor(inputStream.available()));
}catch (Exception e){
throw e;
}finally {
inputStream.close();
closeChannelSftp(channelSftp);
}
} /**
* 获取远程服务器文件列表
* @param session
* @param remotePath
* 远程服务器路径
* @return
* @throws SftpException
*/
public static Vector listFiles(Session session,String remotePath) throws Exception {
ChannelSftp channelSftp = openChannelSftp(session);
try {
Vector vector = channelSftp.ls(remotePath);
return vector;
}catch (Exception e){
throw e;
}finally {
closeChannelSftp(channelSftp);
}
} /**
* 删除文件
* @param session
* @param remotePath
* @param fileName
* @throws Exception
*/
public static void removeFile(Session session,String remotePath,String fileName) throws Exception{
ChannelSftp channelSftp = openChannelSftp(session);
try {
channelSftp.cd(remotePath);
channelSftp.rm(fileName);
}catch (Exception e){
throw e;
}finally {
closeChannelSftp(channelSftp);
}
} /**
* 删除文件夹
* @param session
* @param remotePath
* @throws Exception
*/
public static void removeDir(Session session,String remotePath) throws Exception{
ChannelSftp channelSftp = openChannelSftp(session);
try {
if (remotePath.lastIndexOf("/") == remotePath.length() - 1){
remotePath = remotePath.substring(0,remotePath.length() - 1);
}
String parentDir = remotePath.substring(0,remotePath.lastIndexOf("/") + 1);
String rmDir = remotePath.substring(remotePath.lastIndexOf("/") + 1,remotePath.length());
channelSftp.cd(parentDir);
channelSftp.rmdir(rmDir);
}catch (Exception e){
throw e;
}finally {
closeChannelSftp(channelSftp);
}
} /**
* 新建一个 exec 通道
* @param session
* @return
* @throws JSchException
*/
public static ChannelExec openChannelExec(Session session) throws JSchException {
ChannelExec channelExec = (ChannelExec)session.openChannel("exec");
return channelExec;
} /**
* 关闭 exec 通道
* @param channelExec
*/
public static void closeChannelExec(ChannelExec channelExec){
if (channelExec != null){
channelExec.disconnect();
}
} /**
* 执行 脚本
* @param session
* @param cmd
* 执行 .sh 脚本
* @param charset
* 字符格式
* @return
* @throws IOException
* @throws JSchException
*/
public static String[] execCmd(Session session,String cmd,String charset) throws Exception{
//打开通道
ChannelExec channelExec = openChannelExec(session);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream error = new ByteArrayOutputStream();
channelExec.setCommand(cmd);
channelExec.setOutputStream(out);
channelExec.setErrStream(error);
channelExec.connect();
//确保能够执行完成及响应所有数据
Thread.sleep(10000);
String[] msg = new String[2];
msg[0] = new String(out.toByteArray(),charset);
msg[1] = new String(error.toByteArray(),charset);
out.close();
error.close();
//关闭通道
closeChannelExec(channelExec);
return msg;
} /**
* 创建一个交互式的 shell 通道
* @param session
* @return
* @throws JSchException
*/
public static ChannelShell openChannelShell(Session session) throws JSchException{
ChannelShell channelShell = (ChannelShell)session.openChannel("shell");
return channelShell;
} /**
* 关闭 shell 通道
* @param channelShell
*/
public static void closeChannelShell(ChannelShell channelShell){
if (channelShell != null){
channelShell.disconnect();
}
} /**
* 执行命令
* @param cmds
* 命令参数
* @param session
* @param timeout
* 连接超时时间
* @param sleepTimeout
* 线程等待时间
* @return
* @throws Exception
*/
public static String execShellCmd(String[] cmds,Session session,int timeout,int sleepTimeout) throws Exception {
//打开通道
ChannelShell channelShell = openChannelShell(session);
//设置输入输出流
PipedOutputStream pipedOut = new PipedOutputStream();
ByteArrayOutputStream errorOut = new ByteArrayOutputStream();
channelShell.setInputStream(new PipedInputStream(pipedOut));
channelShell.setOutputStream(errorOut);
channelShell.connect(timeout);
for (String cmd : cmds){
pipedOut.write(cmd.getBytes("UTF-8"));
//线程休眠,保证执行命令后能够及时返回响应数据
Thread.sleep(sleepTimeout); }
String msg = new String(errorOut.toByteArray(),"UTF-8");
log.info(msg);
pipedOut.close();
errorOut.close();
//关闭通道
closeChannelShell(channelShell);
return msg;
} /**
* 创建定时器,清除timeout 的 session 连接
*/
public static void createSessionMonitor(){
if (sessionMonitor == null){
synchronized (SessionMonitor.class){
if (sessionMonitor == null){
//定时器,定时清除失效的session
sessionMonitor = new SessionMonitor();
sessionMonitor.start();
}
}
}
}
/**
* 监控文件传输
*/
static class FileSftpProgressMonitor extends TimerTask implements SftpProgressMonitor{ private long progressInterval = 5 * 1000; // 默认间隔时候为5秒 private boolean isEnd = false; // 记录传输是否停止 private long transfered; // 记录已传输的数据总大小 private long fileSize; // 记录文件总大小 private Timer timer; // 定时器对象 private boolean isScheduled = false; // 记录是否已启动timer定时器 private NumberFormat df = NumberFormat.getInstance(); //格式化 public FileSftpProgressMonitor(long fileSize){
this.fileSize = fileSize;
} @Override
public void run() {
if (!isEnd()){
long transfered = getTransfered();
if (transfered != fileSize){
log.info("Current transfered: " + transfered + " bytes");
sendProgressMessage(transfered);
}else{
log.info("transfered end.");
setIsEnd(true);
}
}else {
log.info("Transfering done. Cancel timer.");
stop(); // 若是传输停止,停止timer记时器
}
} /**
* 定时器关闭
*/
public void stop() {
log.info("Try to stop progress monitor.");
if (timer != null) {
timer.cancel();
timer.purge();
timer = null;
isScheduled = false;
}
log.info("Progress monitor stoped.");
} /**
* 定时器启动
*/
public void start() {
log.info("Try to start progress monitor.");
if (timer == null) {
timer = new Timer();
}
timer.schedule(this, 1000, progressInterval);
isScheduled = true;
log.info("Progress monitor started.");
} /**
* 传输进度
* @param transfered
*/
private void sendProgressMessage(long transfered) {
if (fileSize != 0) {
double d = ((double)transfered * 100)/(double)fileSize;
log.info("Sending progress message: " + df.format(d) + "%");
} else {
log.info("Sending progress message: " + transfered);
}
} @Override
public void init(int i, String s, String s1, long l) {
log.info("transfering start.");
} @Override
public boolean count(long l) {
if (isEnd()){
return false;
}
if (!getIsScheduled()){
start();
}
add(l);
return true;
}
@Override
public void end() {
setIsEnd(false);
log.info("transfering end.");
} private synchronized void add(long count) {
transfered = transfered + count;
} public synchronized boolean isEnd() {
return isEnd;
} public synchronized void setIsEnd(boolean isEnd) {
this.isEnd = isEnd;
} public synchronized long getTransfered() {
return transfered;
} public synchronized void setTransfered(long transfered) {
this.transfered = transfered;
} public synchronized boolean getIsScheduled() {
return isScheduled;
} public synchronized void setIsScheduled(boolean isScheduled) {
this.isScheduled = isScheduled;
} } /**
* 定时器,定时清除失效的session
*/
static class SessionMonitor extends TimerTask{ private Timer timer; // 定时器对象
private long progressInterval = 30 * 1000; // 默认间隔时候为30秒 @Override
public void run() {
if (!cache.isEmpty()){
Iterator iterator = cache.keySet().iterator();
while (iterator.hasNext()){
String key = (String)iterator.next();
//清除失效session
if (testSessionIsDown(key)){
closeLongSessionByKey(key);
}
}
}
} public void start(){
if (timer == null){
timer = new Timer();
}
timer.schedule(this,1000,progressInterval);
} public void stop(){
if (timer != null) {
timer.cancel();
timer.purge();
timer = null;
}
}
}
}

java使用jsch连接linux的更多相关文章

  1. java使用ssh连接Linux并执行命令

     方式1:通过设置账号密码和链接地址 maven pom.xml配置: <dependency>         <groupId>com.jcraft</groupId ...

  2. java之Jsch实现Linux的文件上传与下载

    一.JSch是Java Secure Channel的缩写.JSch是一个SSH2的纯Java实现.它允许你连接到一个SSH服务器,并且可以使用端口转发,X11转发,文件传输等,当然你也可以集成它的功 ...

  3. java使用SSH连接Linux系统

    SSH连接linux系统使我们在开发项目中常用到的,现在留下来,做个记录 package com.log; import java.io.BufferedReader; import java.io. ...

  4. 第3节 sqoop:7、通过java代码远程连接linux执行shell命令

    数据库的数据同步软件sqoop 数据同步 关系型数据库到大数据平台 任务:sqoop 是批量导入数据太慢,如何做到实时的数据同步 实时的数据同步工具: canal 阿里开源的一个数据库数据实时同步的软 ...

  5. java程序远程连接Linux服务器

    JSCH或 Ganymed Ganymed: Ganymed SSH-2 for Java是用纯Java实现SSH-2协议的一个包. 可以利用它直接在Java程序中连接SSH服务器.官网地址为 htt ...

  6. java使用JSCH连接FTP&lpar;Linux服务器&rpar;上传文件到Linux服务器

    首先需要用到jsch-0.1.54.jar 包: 链接: https://pan.baidu.com/s/1kZR6MqwpCYht9Pp_D6NKQw 密码: gywx 直接上代码: package ...

  7. Java中Jedis连接Linux上的Redis出现connect time out&lpar;解决方案&rpar;

    我的代码: /** * * <p>Title: testJedis</p> * <p>Description: 测试单机版的redis连接(每连接一次构建一个对象) ...

  8. JAVA本地远程连接linux程序监控状态

    环境:  1.本地window 2.程序部署在centos   一,启动访问权限安全守护程序 新建文件:jstatd.all.policy ,注意路径 grant codebase "$JA ...

  9. jsch连接Linux工具类

    import com.alibaba.fastjson.JSONObject;import com.jcraft.jsch.*;import org.slf4j.Logger;import org.s ...

随机推荐

  1. selenium结合最新版的sikuli使用

    sikuli安装,下载sikulixsetup-1.1.0.jar,地址:https://launchpad.net/sikuli/sikulix/1.1.0 在装有Java环境的机器上直接双击jar ...

  2. echo print&lpar;&rpar; print&lowbar;r&lpar;&rpar; var&lowbar;dump&lpar;&rpar;的区别

    常用调试方法 echo()可以一次输出多个值,多个值之间用逗号分隔.echo是语言结构(language construct),而并不是真正的函数,因此不能作为表达式的一部分使用. print()函数 ...

  3. NS&lowbar;ENUM vs&period; NS&lowbar;OPTIONS

    NS_ENUM用于定义普通枚举值,NS_OPTIONS用于定义位移相关操作的枚举值: typedef NS_ENUM(NSUInteger, EOCConnectionState) { EOCConn ...

  4. appium 常用api介绍(2)

    前言:接着上一篇继续讲常用的一些api 参考博文:http://blog.csdn.net/bear_w/article/details/50330565 1.send_keys send_keys( ...

  5. FFT一周目开坑!

    先来一段非递归! #include<bits/stdc++.h> using namespace std; #define N ((1<<18)+3) ); struct ve ...

  6. Percona-Xtrabackup 2&period;3&period;3 死锁不再堵塞备份(二)

    在percona-xtrabackup2.1.9下备份: session one:root(yoon)> show tables;+----------------+| Tables_in_yo ...

  7. BZOJ 3926&colon; &lbrack;Zjoi20150&rsqb;诸神眷顾的幻想乡(后缀自动机)

    被这道题坑了= =只与一个空地相连的空地不超过20个只与一个空地相连的空地不超过20个 因为很重要所以说两遍 就是说儿子节点最多只有20个 把这20个节点作为根遍历一遍所得到的tire所得到的所有不同 ...

  8. Android 创建虚拟机时&OpenCurlyDoubleQuote;提示no system images installed for this target”

    经上网查证,发现原因在于CPU/ABI选项无法选择,并显示“No system images installed for this target”,也就是没有适合的系统镜像,通过与安装好了的ADT-b ...

  9. 经过一段的努力,终于成为CSDN博客专家,感谢大家支持

    感谢CSDN提供这么好的一个技术学习平台,通过各路大神的博客我成长了许多,同时也感谢支持我的朋友们,我会继续努力,用心去写好博客.还请继续关注我~ 谢谢!

  10. 5&period;两分钟让你明白app后端有啥用

    app后端,也称为app后台,称呼不一样,但指的是同一个东西. 我一直都以app后端有啥用这个问题不用解释.但在网络上,有准备进行app创业的网友(是从传统行业过来的)问过这个问题,我这里就以app后 ...