
jsch中ChannelShell与ChannelExec区别
发布日期:2021-05-07 04:26:17
浏览次数:29
分类:精选文章
本文共 3470 字,大约阅读时间需要 11 分钟。
环境
jdk:java7
操作系统: win7因为框架jsch
比较老,所以对java
版本要求好低。
分析
框架jsch
我就不说了,很老的框架,现在也不更新了。
最近在用jsch
中的ChannelShell
时,遇到问题:
①这个方法会返回命令提示符,很烦;
比如我要执行下面几个命令:ChannelShell channel = (ChannelShell) session.openChannel("shell"); channel.connect(); InputStream inputStream = channel.getInputStream(); OutputStream outputStream = channel.getOutputStream(); String cmd = "ls \n\r"; outputStream.write(cmd.getBytes()); String cmd2 = "cd /home/jenkins/workspace/ggservice \n\r"; outputStream.write(cmd2.getBytes()); String cmd3 = "pwd \n\r"; outputStream.write(cmd3.getBytes()); outputStream.flush();BufferedReader in = new BufferedReader(new InputStreamReader(inputStream)); String msg = null; while((msg = in.readLine())!=null){ System.out.println(msg); } in.close();
得到的结果是:
Last login: Fri Apr 28 15:07:22 2017 from 192.168.52.63ls cd /home/jenkins/workspace/ggservice pwd [root@master01 ~]# ls bintray-sbt-rpm.repo tables_mysql_innodb.sql[root@master01 ~]# [root@master01 ~]# cd /home/jenkins/workspace/ggservice [root@master01 ggservice]# [root@master01 ggservice]# pwd /home/jenkins/workspace/ggservice[root@master01 ggservice]#
可以看出,连[root@master01 ~]
这样的命令提示符和输入的命令都出来,我其实是不需要这个,我要的只是结果。
②由于使用BufferedReader
的readLine()
方法,结果会产生阻塞。
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream)); String msg = null;while((msg = in.readLine())!=null){ //当所有的命令都执行完毕后,就会产生阻塞 System.out.println(msg);}in.close();
如下图:
为什么会这样呢?
因为我们建立的是shell
管道,并且我们又使用readLine
方法,当命令全部执行完毕后,远程端并不知道执行完毕,还在等待接受数据,所以呢reandLine
就一直阻塞在那里。 即便你换成read
方法还是一样的,因为shell
管道本身就是交互模式的。要想停止,有两种方式: ①人为的发送一个exit
命令,告诉程序本次交互结束啦 ②使用字节流中的available
方法,来获取数据的总大小,然后循环去读。 ①代码:
InputStream inputStream = channel.getInputStream();//从远程端到达的所有数据都能从这个流中读取到 OutputStream outputStream = channel.getOutputStream();//写入该流的所有数据都将发送到远程端。 //使用PrintWriter流的目的就是为了使用println这个方法 //好处就是不需要每次手动给字符串加\n PrintWriter printWriter = new PrintWriter(outputStream); String cmd = "ls"; printWriter.println(cmd); String cmd2 = "cd /home/jenkins/workspace/ggservice"; printWriter.println(cmd2); String cmd3 = "ls"; printWriter.println(cmd3); printWriter.println("exit");//加上个就是为了,结束本次交互 printWriter.flush();BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));String msg = null; while((msg = in.readLine())!=null){ System.out.println(msg); } in.close();
②代码:
...代码省略 ...ChannelShell channel = (ChannelShell) session.openChannel("shell");channel.connect();//从远程端到达的所有数据都能从这个流中读取到InputStream in = channel.getInputStream();//写入该流的所有数据都将发送到远程端。OutputStream outputStream = channel.getOutputStream();byte[] tmp=new byte[1024];while(true){ while(in.available()>0){ int i=in.read(tmp, 0, 1024); if(i<0)break; System.out.print(new String(tmp, 0, i)); } if(channel.isClosed()){ if(in.available()>0) continue; System.out.println("exit-status: "+channel.getExitStatus()); break; }}
这样就不会阻塞啦
最后我就去查ChannelShell和ChannelExec区别
ChannelShell
对于ChannelShell,以输入流的形式,提供命令和输入这些命令,这就像在本地计算机上使用交互式shell
(它通常用于:交互式使用)ChannelExec
对于ChannelExec,在调用connect()方法之前这个命令提供了setCommand()方法,
并且这些命令作为输入将以输入流的形式被发送出去。 (通常,你只能有调用setCommand()方法一次,多次调用只有最后一次生效), 但是你可以使用普通shell的分隔符(&,&&,|,||,; , \n, 复合命令)来提供多个命令。 这就像在你本机上执行一个shell脚本一样(当然,如果一个命令本身就是个交互式shell,这样就像ChannelShell)明显:使用命令通道更容易,因为您不需要处理命令提示符。
参考链接
发表评论
最新留言
逛到本站,mark一下
[***.202.152.39]2025年04月11日 02时22分41秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
考研复试——KY276 Problem C
2021-05-14
老鸟带你画tiled lines
2021-05-14
MybatisPlus自定义Sql实现多表查询
2021-05-15
Java位运算,负数的二进制表示形式,int类型最大值为什么是2的31次方-1
2021-05-15
PyQt5快速上手基础篇10-QSettings用法
2021-05-15
JQuery--手风琴,留言板
2021-05-15
MFC 自定义消息发送字符串
2021-05-15
goahead 下goaction测试与搭建
2021-05-15
Adding Powers
2021-05-15
ideal 下创建springboot项目
2021-05-15
Linux操作系统的安装与使用
2021-05-15
ajax请求出现/[object%20Object]错误的解决办法
2021-05-15
流体运动估计光流算法研究
2021-05-15
如何转载博客
2021-05-15
C++ 继承 详解
2021-05-15
OSPF多区域
2021-05-15
Grafana导入 Promethus node模板
2021-05-15
如何提高SQL查询的效率?
2021-05-15
Docker入门之-镜像(二)
2021-05-15
数据结构——链表(3)
2021-05-15