SSHD实践(四)使用Shell执行远程命令

Sftp
placeholder image
admin 发布于:2023-11-25 23:25:43
阅读:loading

前面介绍了使用Apache Mina的ChannelSftp和SftpFileSystem实现对远程文件的操作,以及使用ChannelExec来执行一些远程服务器的命令,本文继续实践SSHD的系列文章,使用ChannelShell来执行一些远程服务器的命令。

1.基本介绍

在Apache Mina SSHD中,ChannelShell是用于使用交互式shell的类。下面是ChannelShell的详细介绍和特征:

(1)交互式shell支持:ChannelShell允许您在远程服务器上使用交互式shell。它会模拟一个本地shell会话,您可以像在本地shell中一样,在远程服务器上执行命令,并与其进行交互。

(2)命令执行和输出处理:ChannelShell可以执行远程命令,并处理命令的输出。您可以通过输入流将命令写入shell会话,然后通过读取输出流获取命令的输出结果。这使您能够与远程服务器进行实时交互,并获取命令的执行结果。

(3)输入输出流的重定向:ChannelShell可以重定向输入输出流,以便您可以将命令的输入和输出与其他流进行关联。例如,您可以将输入流从文件读取,将输出流写入文件,或将输出流重定向到其他流中。

(4)命令提示符识别:ChannelShell能够识别远程服务器的命令提示符。这对于检测命令执行的状态和处理交互式shell环境非常重要。

(5)命令执行状态处理:通过ChannelShell,您可以获取远程命令的执行状态,例如命令是否成功执行、退出状态等。这使您能够对执行结果进行进一步的处理和决策。

(6)Pty模式支持:ChannelShell支持使用Pty(伪终端)模式执行远程命令。Pty模式提供了更高级的shell交互功能,例如支持终端特殊字符、窗口尺寸调整等。

总的来说,ChannelShell提供了一种通过SSH连接在远程服务器上使用交互式shell的方式。它具有命令输入输出处理、输入输出流重定向、命令提示符识别、命令执行状态处理和Pty模式支持等特性。通过ChannelShell,您可以实时与远程服务器进行交互,并获取命令执行结果。

与 ChannelExec 的对比:

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

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

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

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

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

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

2.代码示例

package cn.chendd.sshd;

import ......;

/**
 * Shell命令测试
 *
 * @author chendd
 * @date 2023/11/20 22:25
 */
@RunWith(JUnit4.class)
public class ShellTest {

    @Test
    public void shellTest() throws IOException {
        SshClient sshClient = SshClient.setUpDefaultClient();
        sshClient.start();
        SftpParam param = new SftpParam();
        ClientSession session = sshClient.connect(param.getUsername(), param.getHost(), param.getPort()).verify(5 , TimeUnit.SECONDS).getSession();
        session.addPasswordIdentity(param.getPassword());
        session.auth().verify();
        String[] commands = new String[] {"ip addr" , "pwd" , "ping -c 5 127.0.0.1" , "ll" , "ls"};
        System.out.println("执行命令列表:" + StringUtils.join(commands , ";"));
        try (ChannelShell channel = session.createShellChannel()) {
            channel.open().verify(5 , TimeUnit.SECONDS);
            // 执行命令
            try (PrintStream out = new PrintStream(channel.getInvertedIn())) {
                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();
            }
            //channel.waitFor(Collections.singleton(ClientChannelEvent.CLOSED), 0);
            try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(channel.getInvertedOut()))) {
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    System.out.println(line);
                }
            }
        }
        session.close();
        sshClient.close();
    }


}

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.示例预览

SSHD远程命令执行Shell.gif

5.其它说明

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

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

(3)本文实现了Apache Mina SSHD实现远程服务器的命令执行,完整示例工程代码可见《附件下载.zip

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

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

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

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

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

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

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


 点赞


 发表评论

当前回复:作者

 评论列表


留言区