Java执行远程服务器上的Shell文件并返回结果

Java执行远程服务器上的Shell文件并返回结果

摘要

Java执行远程服务器上的Shell文件并返回结果

实现目标

java服务在机器A上
shell脚本在机器B上

前提是免密码访问:
A上的/root/.ssh/id_rsa.pub 文件内容已经追加到B上的/root/.ssh/authorized_keys里面

想要实现java服务(A)可以调用shell脚本(B)并且返回执行结果到A。

第三方库jsch

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

一个方法就好

下面的测试方法就是为了在本地执行远程机器192.168.1.108上的/root/test/test.sh脚本。我本机是windows。所以id_rsa的位置是 C:\Users\Administrator\.ssh\id_rsa
C:\Program Files (x86)\Git\bin\ssh-keygen.exe 生成密钥的工具

脚本非常简单,就是列出目录下的文件

#!/bin/bash
cd /root/ngrok
ls -lh

下面是测试方法
虽然jsch支持使用用户名密码的方法访问sshd,但是还是建议使用密钥方式。

package javacore.cn;


import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class ShellKit {

    public static List<String> exe(String dnsName, String privKey, int port, String remoteshellfile) throws IOException {
        JSch jSch = new JSch();
        List<String> result = new ArrayList<String>();
        ChannelExec channelExec = null;
        try {

            //Authenticate through Private Key File
            jSch.addIdentity(privKey);
            //Give the user and dnsName
            Session session = jSch.getSession("root", dnsName, port);
            //Required if not a trusted host
            java.util.Properties config = new java.util.Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            System.out.println("Connecting SSH to " + dnsName + " - Please wait for few minutes... ");
            session.connect();


            //Open a shell
            channelExec = (ChannelExec) (session.openChannel("exec"));

            InputStream in = channelExec.getInputStream();
            channelExec.setCommand(" bash  " + remoteshellfile);

            // Execute the command
            channelExec.connect();
            System.out.println("Executing " + remoteshellfile);

            // Read the output from the input stream we set above
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String line;

            //Read each line from the buffered reader and add it to result list
            // You can also simple print the result here
            while ((line = reader.readLine()) != null) {
                result.add(line);
            }

            //retrieve the exit status of the remote command corresponding to this channel
            int exitStatus = channelExec.getExitStatus();

            //Safely disconnect channel and disconnect session. If not done then it may cause resource leak
            channelExec.disconnect();
            session.disconnect();

            System.out.println("status " + exitStatus);
            if (exitStatus < 0) {
                System.out.println("Done, but exit status not set!");
            } else if (exitStatus > 0) {
                System.out.println("Done, but with error!");
            } else {
                System.out.println("Done!");
            }

        } catch (JSchException e) {
            e.printStackTrace();
        } finally {
            if (channelExec != null) {
                channelExec.disconnect();
            }
        }
        return result;

    }


    public static void main(String[] args) {
        //指定访问私钥
        String privKey = "C:\\Users\\Administrator\\.ssh\\id_rsa";
        try {
            List<String> rs = ShellKit.exe("192.168.1.108", privKey, 22, "/root/test/test.sh");
            for (int i = 0; i < rs.size(); i++) {
                System.out.println(rs.get(i));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

执行结果

Connecting SSH to 192.168.1.108 - Please wait for few minutes... 
Executing /root/test/test.sh
status 0
Done!
总用量 11M
-rwxrwxrwx 1 root root 11M  5月 28 14:30 ngrok
-rw-r--r-- 1 root root  56  6月  6 10:35 ngrok.conf
-rwxrwxrwx 1 root root 111  6月  6 11:31 restart.sh