JSch实践(三)使用Shell执行远程命令

Sftp
placeholder image
admin 发布于:2023-11-24 17:32:39
阅读:loading

前面介绍了使用JSch的ChannelSftp实现对远程文件的操作,也实践了基于ChannelExec执行一些脚本命令,本文继续实践JSch的系列文章,使用ChannelShell来执行一些远程服务器的命令。

1.基本介绍

ChannelShell是 JSch 库提供的另一个类,用于在远程服务器上执行交互式的命令和脚本。下面是一些关于ChannelShell的特征和使用说明:

(1)交互式执行:ChannelShell是一种交互式的通道类型,可以在远程服务器上执行命令并与其进行交互,类似于在终端中操作。

(2)命令执行和结果处理:使用ChannelShell可以执行多个命令,并获取每个命令的执行结果。你可以通过输入流(getInputStream)获取命令执行的标准输出,通过错误流(getErrStream)获取错误信息。

(3)命令的输入和输出:你可以通过输入流(getOutputStream)将命令的输入发送到远程服务器上,并通过输出流(getInputStream)获取命令的输出结果。这样可以实现与远程服务器进行交互,更加灵活和实时。

(4)交互式 Shell:ChannelShell允许你像在终端中一样,以交互式的方式执行命令,包括输入命令、查看输出和错误信息、响应远程服务器的提示符等。

(5)远程 Shell 环境:ChannelShell提供了一个运行在远程服务器上的 Shell 环境,可以执行命令、脚本和其他交互操作,如文件操作、环境变量配置等。

(6)异步执行:与ChannelExec类似,ChannelShell也支持异步执行命令,可以同时执行多个命令并在它们执行完成之前进行其他操作。

(7)安全连接:类似于ChannelExec, ChannelShell也基于 JSch 库,提供了安全的远程连接和交互,支持通过 SSH 协议进行加密和身份验证。

与 ChannelExec 的对比:

① ChannelExec适用于执行非交互式的命令,并获取其执行结果。

② ChannelShell则是为了执行交互式的命令和与远程服务器进行交互而设计。

③ ChannelShell可以在执行命令后等待并读取远程服务器的输出,然后进行下一步命令或响应。这使得它适用于需要实时交互和响应远程服务器的场景。

④ ChannelShell可以模拟终端的环境,执行更复杂的命令和操作,而ChannelExec更适合执行简单的单个命令。

通常情况下,如果只需要执行一两个简单的命令并获取结果,则使用ChannelExec更直观和简单。如果需要与远程服务器进行交互或执行复杂的脚本,则使用ChannelShell更为适合。

综上所述,ChannelShell类提供了在远程服务器上执行交互式命令和脚本,并与其进行实时交互的功能。与 ChannelExec 相比,可以更灵活地与远程服务器进行交互和执行复杂的命令。

2.代码示例

package cn.chendd.jsch;

import ...;

/**
 * Shell命令测试
 *
 * @author chendd
 * @date 2023/11/18 15:23
 */
@RunWith(JUnit4.class)
public class ShellTest {

    @Test
    public void shellTest() throws JSchException, IOException {
        JSch jsch = new JSch();
        SftpParam param = new SftpParam();
        Session session = null;
        ChannelShell channel;
        try {
            session = jsch.getSession(param.getUsername(), param.getHost(), param.getPort());
            final String password = param.getPassword();
            if (StringUtils.isNotEmpty(password)) {
                session.setPassword(password);
            }
            session.setTimeout(param.getTimeout());
            session.setConfig("StrictHostKeyChecking" , "no");
            session.connect();
            channel = (ChannelShell) session.openChannel("shell");
        } catch (JSchException e) {
            if (session != null) {
                session.disconnect();
            }
            throw new RuntimeException(e);
        }
        try {
            this.shellTest(channel);
        } finally {
            channel.disconnect();
            session.disconnect();
        }
    }

    private void shellTest(ChannelShell channel) throws JSchException, IOException {
        channel.connect();

        //如果什么都不输出:Last login: Fri Nov 17 15:29:09 2023 from 192.168.244.1
        try (PrintStream out = new PrintStream(channel.getOutputStream())) {
            out.println("pwd");
            out.flush();
            out.println("ip addr");
            out.flush();
            out.println("ping -c 5 127.0.0.1");
            out.flush();
            out.println("ll");
            out.flush();
            out.println("ls");
            out.flush();
            out.println("exit");
            out.flush();
        }

        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(channel.getInputStream()))) {
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                System.out.println(line);
            }
        }
    }

}

3.示例说明

(1)代码为示例,写的比较随意,某些IO资源的释放应以更严格的形式编写;

(2)执行的命令共计5个,分别如下:

   ① ip addr:输出本机的IP地址信息;

   ② pwd:输出当前上下文的所在路径;

   ③ ping -c 5 127.0.0.1:获取与本机的网络连接,共计输出5次;

   ④ ll:获取当前路径的文件夹结构列表;

   ⑤ ls:获取当前路径的文件夹内的文件和文件夹名称列表;

   ⑥ exit:所有命令执行完毕后,上述代码中的 readLine 方法处于阻塞状态,若想结束则可以执行 exit 命令使得 session 会话退出;

(3)执行的命令共计5个,分别如下:

4.示例预览

JSch使用Shell执行命令.gif

5.其它说明

(1)本次实践JSch共计三块知识,分别是使用Sftp访问远程服务器、Exec执行远程服务器命令、Shell执行远程服务器命令,至于它还可以作用于的端口转发等功能不做摸索;;

(2)本文实现了JSch的基于ChannelShell执行远程命令的示例,在命令执行的同时也可实时输出命令执行的结果输出;

(3)附件下载;

(4)ChannelExec和ChannelShell二者除了上面介绍的区别之外,我从示例实践的角度再补充几条:

① Shell更加细粒度的还原了命令执行时的过程,包含各个命令执行时的上下文输出;

② Shell执行时会多输出各个命令的执行语句;

③ Shell命令输出的内容包含了特殊的富文本,在IDEA的控制台可以被高亮输出;

④ Exec命令执行`ls`命令时,无结果输出,Shell命令可以获得Shell命令输出结果;

⑤ Shell命令执行完毕后仍处于阻塞状态,等待后续新的命令,Exec命令执行完毕就直接退出了(示例中增加了exit来退出阻塞);

所以,若是需要执行远程服务器的命令,我推荐使用ChannelShell。

 点赞


 发表评论

当前回复:作者

 评论列表


留言区