SSH-2实现java连接远程服务器并执行脚本命令

参考文档:

    maven jar包:https://mvnrepository.com/artifact/ch.ethz.ganymed/ganymed-ssh2

    Ganymed SSH2 API文档 :http://www.ganymed.ethz.ch/ssh2/javadoc/overview-summary.html

Java的Ganymed SSH2是一个在纯Java中实现SSH-2协议的库(在J2SE 1.4.2和5.0上测试过)。
它允许从Java程序中连接到SSH服务器。
它支持SSH会话(远程命令执行和shell访问)、本地和远程端口转发、本地流转发、X11转发、SCP和SFTP。

不依赖于任何JCE提供程序,因为所有加密功能都包含在内。

API简介
一、API中常用的几个类
Connection:创建服务器连接以及认证(用户名密码认证、秘钥认证等)
Session :会话
SCPClient:可用于文件在不同服务器之间复制。在服务器端,路径必须存在,如果不存在会报错。
线程安全的——您可以同时下载(和上传)不同的文件集,没有任何问题。
SCPClient实际上是将每个请求映射到不同的会话。

SFTPv3Client: 执条单个指令(推荐使用) 提供了很多方法

二、使用步骤

    1、creates a Connection object.
    2、calls the connect() method.
    3、calls some of the authentication methods (e.g., authenticateWithPublicKey()).

    4、calls one or several times the openSession() method.

三、需要注意

    1、认证成功后,当前目录就位于/home/username/目录之下,
        你可以指定脚本文件所在的绝对路径,或者通过cd导航到脚本文件所在的目录,
        然后传递执行脚本所需要的参数,完成脚本调用执行。
    2、执行脚本以后,可以获取脚本执行的结果文本,需要对这些文本进行正确编码后返回给客户端,避免乱码产生
    3、如果你需要执行多个linux控制台脚本,比如第一个脚本的返回结果是第二个脚本的入参,你必须打开多个Session,也就是多次调用Session sess = conn.openSession();,使用完毕记得关闭就可以了

四、代码

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
 
import org.apache.log4j.Logger;
 
import com.viewhigh.vadp.framework.data.util.StringUtils;
 
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
 
/**
 * 
 * 描述:连接linux服务器并执行相关的shell命令
 * 作者:cuicx
 * 版本:V1.0
 * 创建日期:2018年7月4日 
 * 修改日期: 2018年7月4日
 */
public class ConnectLinuxCommand {
    private static final Logger logger = Logger.getLogger(ConnectLinuxCommand.class);
 
    private static String DEFAULTCHARTSET = "UTF-8";
    private static Connection conn;
    /**
     * 
     * @Title: login  
     * @Description: 用户名密码方式  远程登录linux服务器
     * @return: Boolean     
     * @throws
     */
    public static Boolean login(RemoteConnect remoteConnect) {
        boolean flag = false;
        try {
            conn = new Connection(remoteConnect.getIp());
            conn.connect();// 连接
            flag = conn.authenticateWithPassword(remoteConnect.getUserName(), remoteConnect.getPassword());// 认证
            if (flag) {
                logger.info("认证成功!");
            } else {
                logger.info("认证失败!");
                conn.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return flag;
    }
    /**
     * 
    * @Title: loginByKey
    * @Description: 秘钥方式  远程登录linux服务器
    * @param remoteConnect 
    * @param keyFile  一个文件对象指向一个文件,该文件包含OpenSSH密钥格式的用户的DSA或RSA私钥(PEM,不能丢失"-----BEGIN DSA PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----"标签
    * @param keyfilePass 如果秘钥文件加密 需要用该参数解密,如果没有加密可以为null
    * @return Boolean
    * @throws
     */
    public static Boolean loginByFileKey(RemoteConnect remoteConnect, File keyFile, String keyfilePass) {
        boolean flag = false;
        // 输入密钥所在路径
        // File keyfile = new File("C:\\temp\\private");
        try {
            conn = new Connection(remoteConnect.getIp());
            conn.connect();
            // 登录认证
            flag = conn.authenticateWithPublicKey(remoteConnect.getUserName(), keyFile, keyfilePass);
            if (flag) {
                logger.info("认证成功!");
            } else {
                logger.info("认证失败!");
                conn.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }
    
    /**
     * 
    * @Title: loginByCharsKey
    * @Description: 秘钥方式  远程登录linux服务器
    * @param remoteConnect
    * @param keys  一个字符[],其中包含用户的DSA或RSA私钥(OpenSSH密匙格式,您不能丢失“----- begin DSA私钥-----”或“-----BEGIN RSA PRIVATE KEY-----“标签。char数组可以包含换行符/换行符。
    * @param keyPass 如果秘钥字符数组加密  需要用该字段解密  否则不需要可以为null 
    * @return Boolean
    * @throws
     */
    public static Boolean loginByCharsKey(RemoteConnect remoteConnect, char[] keys, String keyPass) {
        boolean flag = false;
        // 输入密钥所在路径
        // File keyfile = new File("C:\\temp\\private");
        try {
            conn = new Connection(remoteConnect.getIp());
            conn.connect();
            // 登录认证
            flag = conn.authenticateWithPublicKey(remoteConnect.getUserName(), keys, keyPass);
            if (flag) {
                logger.info("认证成功!");
            } else {
                logger.info("认证失败!");
                conn.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }
    /**
     * 
     * @Title: execute  
     * @Description: 远程执行shll脚本或者命令
     * @param cmd 脚本命令
     * @return: result 命令执行完毕返回结果     
     * @throws
     */
    public static String execute(String cmd){
        String result = "";
        try {
            Session session = conn.openSession();// 打开一个会话
            session.execCommand(cmd);// 执行命令
            result = processStdout(session.getStdout(), DEFAULTCHARTSET);
            // 如果为得到标准输出为空,说明脚本执行出错了
            if (StringUtils.isBlank(result)) {
                result = processStdout(session.getStderr(), DEFAULTCHARTSET);
            }
            conn.close();
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
    /**
    * @Title: executeSuccess
    * @Description: 远程执行shell脚本或者命令
    * @param shell脚本或者命令
    * @return String 命令执行成功后返回的结果值,如果命令执行失败,返回空字符串,不是null
    * @throws
     */
    public static String executeSuccess(String cmd){
        String result = "";
        try {
            Session session = conn.openSession();// 打开一个会话
            session.execCommand(cmd);// 执行命令
            result = processStdout(session.getStdout(), DEFAULTCHARTSET);
            conn.close();
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
    /**
     * 
    * @Title: processStdout
    * @Description: 解析脚本执行的返回结果
    * @param in 输入流对象
    * @param charset 编码
    * @return String 以纯文本的格式返回
    * @throws
     */
    public static String processStdout(InputStream in, String charset){
        InputStream stdout = new StreamGobbler(in);
        StringBuffer buffer = new StringBuffer();
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(stdout, charset));
            String line = null;
            while ((line = br.readLine()) != null) {
                buffer.append(line + "\n");
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer.toString();
    }
    
    /**
     * 
    * @Title: ConnectLinux
    * @Description: 通过用户名和密码关联linux服务器
    * @return
    * @return String
    * @throws
     */
    public static boolean connectLinux(String ip,String userName,String password,String commandStr) {
        
        logger.info("ConnectLinuxCommand  scpGet===" + "ip:" + ip + "  userName:" + userName + "  commandStr:"
                + commandStr);
        
        String returnStr = "";
        boolean result = true;
        RemoteConnect remoteConnect = new RemoteConnect();
        remoteConnect.setIp(ip);
        remoteConnect.setUserName(userName);
        remoteConnect.setPassword(password);
        try {
            if (login(remoteConnect)) {
                returnStr = execute(commandStr);
                System.out.println(result);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (StringUtils.isBlank(returnStr)) {
            result = false;
        }
        return result;
    }
    /**
     * 
    * @Title: scpGet
    * @Description: 从其他服务器获取文件到本服务器指定目录
    * @param host ip(其他服务器)
    * @param username 用户名(其他服务器)
    * @param password 密码(其他服务器)
    * @param remoteFile 文件位置(其他服务器)
    * @param localDir 本服务器目录
    * @throws IOException
    * @return void
    * @throws
     */
    public static void scpGet(String ip, String userName, String password, String remoteFile, String localDir)
            throws IOException {
        
        logger.info("ConnectLinuxCommand  scpGet===" + "ip:" + ip + "  userName:" + userName + "  remoteFile:"
                + remoteFile + "  localDir:" + localDir);
        RemoteConnect remoteConnect = new RemoteConnect();
        remoteConnect.setIp(ip);
        remoteConnect.setUserName(userName);
        remoteConnect.setPassword(password);
        if (login(remoteConnect)) {
            SCPClient client = new SCPClient(conn);
            client.get(remoteFile, localDir);
            conn.close();
        }
    }
    /**
     * 
    * @Title: scpPut
    * @Description: 将文件复制到其他计算机中
    * @param host 
    * @param username
    * @param password
    * @param localFile
    * @param remoteDir
    * @throws IOException
    * @return void
    * @throws
     */
    public static void scpPut(String ip, String userName, String password, String localFile, String remoteDir)
            throws IOException {
        logger.info("ConnectLinuxCommand  scpPut===" + "ip:" + ip + "  userName:" + userName + "  localFile:"
                + localFile + "  remoteDir:" + remoteDir);
        RemoteConnect remoteConnect = new RemoteConnect();
        remoteConnect.setIp(ip);
        remoteConnect.setUserName(userName);
        remoteConnect.setPassword(password);
        if (login(remoteConnect)) {
            SCPClient client = new SCPClient(conn);
            client.put(localFile, remoteDir);
            conn.close();
        }
    }
}
public class RemoteConnect {
    
    private String ip;
    
    private String userName;
    
    private String password;
 
    public String getIp() {
        return ip;
    }
 
    public void setIp(String ip) {
        this.ip = ip;
    }
 
    public String getUserName() {
        return userName;
    }
 
    public void setUserName(String userName) {
        this.userName = userName;
    }
 
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
}
public class CcxTest {
 
       @Test
        public void testDemo() {
           //cd /home/ubuntu/Desktop/music_rec/user_sim/result;cat xyy_result_m10d.json
           //String commandStr="cd /home;rm -rf aa.txt";
           String commandStr="cd /home;cat aa.txt;rm -rf aa.txt";
           Boolean result=ConnectLinuxCommand.connectLinux("192.168.0.11","root","123456",commandStr);
           System.out.println(result);
        }
       @Test
       public void testDemo2() throws IOException {
           try {
               ConnectLinuxCommand.scpGet("192.168.0.11","root","123456", "test.txt", "/home/");
            } catch (Exception e) {
                e.printStackTrace();
            }
       }
       
       @Test
       public void testDemo3() {
           try {
               ConnectLinuxCommand.scpPut("192.168.0.11","root","123456", "test.txt", "/home/");
            } catch (Exception e) {
                e.printStackTrace();
            }
           
           
       }
        
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容