0
点赞
收藏
分享

微信扫一扫

JAVA实现远程登录主机并执行命令(密码登录和免密登录)

人间四月天i 2022-03-30 阅读 73
sshjava

引入ssh相关依赖,以maven为例

<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.55</version>
</dependency>

导入工具类

import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.KeyPair;
import com.jcraft.jsch.Session;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Objects;

/**
 * ssh 连接工具类
 */
public class SSHTools {

    private static final Logger logger = LoggerFactory.getLogger(SSHTools.class);

    private Session session;

    /**
     * 获取实例
     *
     * @return 实例
     */
    public static SSHTools getInstance() {
        return new SSHTools();
    }

    /**
     * 登录主机
     * <p>
     * 密码登录
     *
     * @param hostIp   主机IP
     * @param hostPort 主机ssh端口
     * @param user     主机登录用户名
     * @param password 主机登录密码
     */
    private void loginByPassword(@NotNull String hostIp,
                                 @NotNull Integer hostPort,
                                 @NotNull String user,
                                 @NotNull String password) {
        try {
            JSch jsch = new JSch();
            session = jsch.getSession(user, hostIp, hostPort);
            session.setPassword(password);
            // 设置第一次登陆的时候提示,可选值:(ask | yes | no)
            session.setConfig("StrictHostKeyChecking", "no");
            // 连接超时
            session.connect(1000 * 10);
        } catch (JSchException e) {
            logger.error("登录时发生错误!", e);
        }
    }

    /**
     * 登录主机
     * <p>
     * 密钥登录
     *
     * @param hostIp     主机IP
     * @param hostPort   主机ssh端口
     * @param user       主机登录用户名
     * @param privateKey 密钥
     */
    private void loginByKey(@NotNull String hostIp,
                            @NotNull Integer hostPort,
                            @NotNull String user,
                            @NotNull String privateKey) {
        try {
            JSch jsch = new JSch();
            jsch.addIdentity(user, privateKey.getBytes(), null, null);
            session = jsch.getSession(user, hostIp, hostPort);
            // 设置第一次登陆的时候提示,可选值:(ask | yes | no)
            session.setConfig("StrictHostKeyChecking", "no");
            // 连接超时
            session.connect(1000 * 10);
        } catch (JSchException e) {
            logger.error("登录时发生错误!", e);
        }
    }

    /**
     * 登录后,主机执行指定命令
     *
     * @param command 命令
     * @return 执行命令后结果
     */
    public String executeShell(@NotNull String command) throws Exception {
        logger.info("exe cmd: {}", command);

        byte[] tmp = new byte[1024];
        // 命令返回的结果
        StringBuilder resultBuffer = new StringBuilder();

        ChannelExec exec = (ChannelExec) session.openChannel("exec");
        exec.setCommand(command);
        exec.connect();

        // 返回结果流(命令执行错误的信息通过getErrStream获取)
        InputStream stdStream = exec.getInputStream();
        try {
            // 开始获得SSH命令的结果
            while (true) {
                while (stdStream.available() > 0) {
                    int i = stdStream.read(tmp, 0, 1024);
                    if (i < 0) {
                        break;
                    }
                    resultBuffer.append(new String(tmp, 0, i));
                }
                if (exec.isClosed()) {
                    break;
                }
                try {
                    Thread.sleep(200);
                } catch (Exception e) {
                    logger.error("执行命令发生错误!", e);
                }
            }
        } finally {
            if (exec.isConnected()) {
                exec.disconnect();
            }
        }
        String result = resultBuffer.toString();
        logger.info("exe cmd return : {}", result);
        return result;
    }

    /**
     * 关闭连接
     */
    public void close() {
        if (Objects.nonNull(session) && session.isConnected()) {
            session.disconnect();
        }
    }

    /**
     * 生成SSH RSA密钥对
     *
     * @param comment 公钥注释
     * @return L 公钥  R 私钥
     */
    public static Pair<String, String> generateKeyPair(String comment) throws JSchException {
        JSch jsch = new JSch();
        KeyPair keyPair = KeyPair.genKeyPair(jsch, KeyPair.RSA);
        ByteArrayOutputStream baos;
        //私钥
        baos = new ByteArrayOutputStream();
        keyPair.writePrivateKey(baos);
        String privateKeyString = baos.toString();
        //公钥
        baos = new ByteArrayOutputStream();
        keyPair.writePublicKey(baos, comment);
        String publicKeyString = baos.toString();
        keyPair.dispose();
        return Pair.of(publicKeyString, privateKeyString);
    }
}

密码登录并执行命令demo

    public static void main(String[] args) throws Exception {
        SSHTools sshTools = SSHTools.getInstance();
        try {
            //1.密码登录主机
            sshTools.loginByPassword("主机ip", 22, "root", "主机用户密码");
            //2.执行命令 例如:查看 data 目录下文件
            String executeShell = sshTools.executeShell("ls /data/");
            //3.打印执行结果
            System.out.println(executeShell);
        }finally {
            //4.释放资源
            sshTools.close();
        }
    }

免密登录并执行命令demo

    public static void main(String[] args) throws Exception {
        //1.生成密钥
        Pair<String, String> pair = SSHTools.generateKeyPair("根据业务随便填");
        //私钥
        String privateKeyString = pair.getRight();
        //公钥
        String publicKeyString = pair.getLeft();

        //2.将公钥去要登录的主机上授权 ,, 去对应的机器上执行以下授权命令   publicKeyString
        String command = "cd ~ && if [ ! -d .ssh ];then mkdir -p .ssh ;fi && cd .ssh && echo " + publicKeyString + " >> authorized_keys && chmod 700 ~/.ssh && chmod 600 authorized_keys"
        //获取公钥授权命令
        System.out.println(command);


        //3.执行完授权命令后就可以免密登录主机了
        SSHTools sshTools = SSHTools.getInstance();
        try {
            //1.免密登录主机
            sshTools.loginByKey("主机ip", 22, "root", privateKeyString);
            //2.执行命令 例如查看 data 目录下文件
            String executeShell = sshTools.executeShell("ls /data/");
            //3.打印执行结果
            System.out.println(executeShell);
        } finally {
            //4.释放资源
            sshTools.close();
        }
    }
举报

相关推荐

0 条评论