【问题标题】:multiple shell script execution using jsch使用 jsch 执行多个 shell 脚本
【发布时间】:2014-05-30 07:36:28
【问题描述】:

我正在使用 Jsch 库在几台 linux 机器上执行大约 1000 个不同的 shell 脚本并将状态更新到一个表中。

我使用了 jsch exec 通道 [ChannelExec],它仅适用于单个脚本,如果 shell 脚本调用另一个脚本,ChannelExec 不会给出正确的结果。

现在我正在使用 jsch 的 shell 通道。它可以很好地从任何类型的 shell 脚本中获取输出。

问题是,如果我一次执行多个 shell 脚本,我会得到一个批量的所有结果。

没有办法让一个 Shell 脚本执行并收到它的结果。

如果我想获得单个脚本的执行结果,我需要为每个脚本执行登录机器,这需要很长时间。

有人可以发布解决方案,建议如何进行,登录机器一次并执行多个脚本并单独接收每个脚本结果。

import com.jcraft.jsch.Channel;
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.io.OutputStream;
import java.io.PrintStream;

public class JschShellExample {

    public static void main(String[] args) {

        try {
            JSch jsch = new JSch();

            Session session = jsch.getSession("user", "10.32.248.158", 22);
            session.setPassword("password");

            java.util.Properties config = new java.util.Properties();
            config.put("StrictHostKeyChecking", "no");
            config.put("PreferredAuthentications","publickey,keyboard-interactive,password");
            session.setConfig(config);
            session.connect(100);

            Channel channel = session.openChannel("shell");

            OutputStream inputstream_for_the_channel = channel.getOutputStream();
            PrintStream commander = new PrintStream(inputstream_for_the_channel, true);

            channel.setOutputStream(null);
            channel.connect(100);
            //shell script
            commander.println("cd /user/home/work ; ./checkstaus.sh ; exit");
            commander.flush();

            System.out.println(channel.getExitStatus());

            InputStream outputstream_from_the_channel = channel.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(outputstream_from_the_channel));
            String line = null;
            StringBuilder sb = new StringBuilder();
            boolean isloginStringPassed = false ;

            while ((line = br.readLine()) != null) {
                    sb.append(line.trim());
            }
            System.out.println("Result ="+sb.toString());

            channel.disconnect();
            session.disconnect();
            System.out.println("completed .. ");
        } catch (JSchException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}

【问题讨论】:

    标签: java shell unix expect jsch


    【解决方案1】:

    通常,当您第一次连接到远程计算机并执行命令后,您会在输出流中打印出shell command line prompt。您可以将其用作不同 shell 命令输出之间的标记。

    您可以考虑使用Expect-like 第三方库,它可以简化远程服务的使用和捕获输出。您可以尝试一系列不错的选择:

    然而,当我要解决类似的问题时,我发现这些库相当陈旧,很难在商业软件中使用。所以我创建了自己的,并提供给其他人。它叫ExpectIt。我的图书馆的优势在project home page 上有说明。

    以下是与公共远程 SSH 服务交互的示例:

        JSch jSch = new JSch();
        Session session = jSch.getSession("new", "sdf.org");
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);
        session.connect();
        Channel channel = session.openChannel("shell");
    
        Expect expect = new ExpectBuilder()
                .withOutput(channel.getOutputStream())
                .withInputs(channel.getInputStream(), channel.getExtInputStream())
                .withEchoOutput(adapt(System.out))
        //        .withInputFilters(removeColors(), removeNonPrintable())
                .withErrorOnTimeout(true)
                .build();
        // try-with-resources is omitted for simplicity
        channel.connect();
        expect.expect(contains("[RETURN]"));
        expect.sendLine();
        String ipAddress = expect.expect(regexp("Trying (.*)\\.\\.\\.")).group(1);
        System.out.println("Captured IP: " + ipAddress);
        expect.expect(contains("login:"));
        expect.sendLine("new");
        expect.expect(contains("(Y/N)"));
        expect.send("N");
        expect.expect(regexp(": $"));
        // finally is omitted
        channel.disconnect();
        session.disconnect();
        expect.close();
    

    您还可以查看this 示例与捕获单个命令输出的 Karaf shell 交互。

    【讨论】:

    • 您好,感谢您的回复,我会试试这个并接受您的回答。
    猜你喜欢
    • 1970-01-01
    • 2011-08-15
    • 2011-10-01
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多