作者:BaseCN Email:basecn@163.com

-----------------------------------------------

Jsch是JAVA的SSH客户端,使用的目的是执行远程服务器上的命令。

关于Session的使用,创建连接后这个session是一直可用的,所以不需要关闭。由Session中open的Channel在使用后应该关闭。

测试了exec的方式,具体参考jsch自带example中的Exec.java。

有两个问题:

1、无法执行多条命令,每次ChannelExec在connect前要先setCommand,最后一次的设置生效。

2、由于第一个原因的限制,如果执行的命令需要环境变量(如JAVA_HOME),就没有办法了。这种方式执行基本的ls,ps之类的命令没有问题,需要复杂的环境变量时有点力不从心。

要是哪位知道exec如何解决上面现两个问题,请分享一下!

-----------------------------------------------

虽然exec可以得到命令的执行结果,但无法满足应用,无奈之下放弃exec转而使用ChannelShell。

在使用ChannelShell的时候需要特别关注jsch的输入和输出流的设置。

输出

为了得到脚本的运行结果,设置jsch的outputStream为FileOutputStream,把shell的输出结果保存到本地文件。虽然最简单的方式是设置System.out为jsch的OutputStream,在控制台看到结果,只是无法保存下来。

FileOutputStream fileOut =newFileOutputStream( outputFileName );

channelShell.setOutputStream( fileOut );

输入

短时间运行的程序,输入可以直接设置为System.in,而长期运行的程序不能使用人工方式输入,必须由程序自动生成命令来执行。所以使用PipeStream来实现字符串输入命令:

PipedInputStream pipeIn =newPipedInputStream();

PipedOutputStream pipeOut = newPipedOutputStream( pipeIn );

channelShell.setInputStream( pipeIn );

调用pipeOut.write( cmd.getBytes() );把生成的命令输出给ssh。

运行

jsch是以多线程方式运行的,所以代码在connect后如果不disconnect Channel和Session,以及相关的Stream,程序会一直等待,直到关闭,目前还没有找到判断关闭或主动关闭的方法,相信应该有这方面的机制。

要注意一个问题,相关的Stream和Channel是一定要关闭的,那么应该在什么时候来关。执行connect后,jsch接收客户端结果需要一定的时间(以秒计),如果马上关闭session就会发现什么都没接收到或内容不全。

可以采取两个办法来解决这个问题,一个开源一个节流

1、在connect增加一个等待延迟,等待1~2秒,这个是开源;

2、减小server端脚本的执行时间,这个是节流。给命令加上"nohup XXXX > output &",以后台方式运行,并把运行结果输出到服务器端的本地目录下。这样脚本的执行时间可以是最小。

-----------------------------------------------

最后还有一点注意,使用shell时,看到有的朋友说执行后没有结果。解决的办法是在命令后加上"/n"字符,server端就认为是一条完整命令了。很奇怪的特性!

-----------------------------------------------

附上类代码

packagejsch;

importstaticjava.lang.String.format;

importjava.io.Closeable;

importjava.io.FileOutputStream;

importjava.io.IOException;

importjava.io.InputStream;

importjava.io.PipedInputStream;

importjava.io.PipedOutputStream;

importcom.jcraft.jsch.ChannelExec;

importcom.jcraft.jsch.ChannelShell;

importcom.jcraft.jsch.JSch;

importcom.jcraft.jsch.Session;

importcom.jcraft.jsch.UserInfo;

importcom.nsm.hermes.wand.Wand;

publicclassSshExecuter

implementsCloseable{

staticlonginterval = 1000L;

staticinttimeout =3000;

privateSshInfo sshInfo =null;

privateJSch jsch =null;

privateSession session =null;

privateSshExecuter( SshInfo info )throwsException{

sshInfo = info;

jsch = newJSch();

jsch.addIdentity( sshInfo.getKey() );

session = jsch.getSession(  sshInfo.getUser(),

sshInfo.getHost(),

sshInfo.getPort() );

UserInfo ui = newSshUserInfo( sshInfo.getPassPhrase() );

session.setUserInfo( ui );

session.connect();

}

publiclongshell( String cmd, String outputFileName )

throwsException{

longstart = System.currentTimeMillis();

ChannelShell channelShell = (ChannelShell)session.openChannel( "shell");

PipedInputStream pipeIn = newPipedInputStream();

PipedOutputStream pipeOut = newPipedOutputStream( pipeIn );

FileOutputStream fileOut = newFileOutputStream( outputFileName );

channelShell.setInputStream( pipeIn );

channelShell.setOutputStream( fileOut );

channelShell.connect( timeout );

pipeOut.write( cmd.getBytes() );

Thread.sleep( interval );

pipeOut.close();

pipeIn.close();

fileOut.close();

channelShell.disconnect();

returnSystem.currentTimeMillis() - start;

}

publicintexec( String cmd )

throwsException{

ChannelExec channelExec = (ChannelExec)session.openChannel( "exec");

channelExec.setCommand( cmd );

channelExec.setInputStream( null);

channelExec.setErrStream( System.err );

InputStream in = channelExec.getInputStream();

channelExec.connect();

intres = -1;

StringBuffer buf = newStringBuffer(1024);

byte[] tmp =newbyte[1024];

while(true) {

while( in.available() >0) {

inti = in.read( tmp,0,1024);

if( i <0)break;

buf.append( newString( tmp,0, i ) );

}

if( channelExec.isClosed() ) {

res = channelExec.getExitStatus();

System.out.println( format( "Exit-status: %d", res ) );

break;

}

Wand.waitA( 100);

}

System.out.println( buf.toString() );

channelExec.disconnect();

returnres;

}

publicstaticSshExecuter newInstance()

throwsException{

String host = "localhost";

Integer port = 22;

String user = "hadoop";

String key = "./id_dsa";

String passPhrase = "";

SshInfo i = newSshInfo( host, port, user, key, passPhrase );

returnnewSshExecuter( i );

}

publicSession getSession(){

returnsession;

}

publicvoidclose()

throwsIOException{

getSession().disconnect();

}

}

classSshInfo{

String host = null;

Integer port = 22;

String user = null;

String key = null;

String passPhrase = null;

publicSshInfo( String host,

Integer port,

String user,

String key,

String passPhrase ){

super();

this.host = host;

this.port = port;

this.user = user;

this.key = key;

this.passPhrase = passPhrase;

}

publicString getHost(){

returnhost;

}

publicInteger getPort(){

returnport;

}

publicString getUser(){

returnuser;

}

publicString getKey(){

returnkey;

}

publicString getPassPhrase(){

returnpassPhrase;

}

}

classSshUserInfoimplementsUserInfo{

privateString passphrase =null;

publicSshUserInfo( String passphrase ){

super();

this.passphrase = passphrase;

}

publicString getPassphrase(){

returnpassphrase;

}

publicString getPassword(){

returnnull;

}

publicbooleanpromptPassphrase( String pass ){

returntrue;

}

publicbooleanpromptPassword( String pass ){

returntrue;

}

publicbooleanpromptYesNo( String arg0 ){

returntrue;

}

publicvoidshowMessage( String m ){

System.out.println( m );

}

}

java jsch 调用shell_使用Jsch执行Shell脚本相关推荐

  1. python 执行shell_从python执行Shell脚本与变量

    我有这个代码: opts.info("Started domain %s (id=%d)" % (dom,domid)) 我想从上面执行一个带有参数domid的shell脚本. 这 ...

  2. Windows IEDA 编译Hbase源码报错 - 无法执行shell脚本

    windows 下编译 hbase源码,报错 [ERROR] Command execution failed. java.io.IOException: Cannot run program &qu ...

  3. java 调用casperjs_Java程序去调用并执行shell脚本及问题总结(推荐)

    摘要: 该文章来自阿里巴巴技术协会(ATA)精选集 背景 我们在开发过程中,大部分是java开发, 而在文本处理过程中,主要就是脚本进行开发. java开发的特点就是我们可以很早地进行TDDL, ME ...

  4. 脚本运行显示服务器超时,java执行shell脚本超时

    java执行shell脚本超时 [2021-02-11 04:20:34]  简介: 系统运维 在数据库运维的过程中,Shell 脚本在很大程度上为运维提供了极大的便利性.而shell 脚本参数作为变 ...

  5. python调用shell脚本的参数_使用python执行shell脚本 并动态传参 及subprocess的使用详解

    最近工作需求中 有遇到这个情况 在web端获取配置文件内容 及 往shell 脚本中动态传入参数 执行shell脚本这个有多种方法 最后还是选择了subprocess这个python标准库 subpr ...

  6. Java程序定时执行shell脚本

    第一次写博客,写的不好还请见谅. 之前在Linux环境中想定期执行某个脚本,第一反应就是将这个task加入到crontab里(crontab的知识点这里就不具体介绍了),当然,这种做法一般情况下是可行 ...

  7. java执行shell脚本 process.waitFor()返回1

    记录一下今天遇到的一个问题 在java代码中执行shell脚本,部分代码如下 Process p = null; List<String> cmds = new ArrayList< ...

  8. 运维经验分享(六)-- 深究crontab不能正确执行Shell脚本的问题(二)

    运维经验分享作为一个专题,目前共7篇文章 <运维经验分享(一)-- Linux Shell之ChatterServer服务控制脚本> <运维经验分享(二)-- Linux Shell ...

  9. Linux中执行shell脚本的4种方法

    这篇文章主要介绍了Linux中执行shell脚本的4种方法总结,即在Linux中运行shell脚本的4种方法,需要的朋友可以参考下. bash shell 脚本的方法有多种,现在作个小结.假设我们编写 ...

最新文章

  1. 【C++】Google C++编码规范(一):作用域
  2. HTML5中aside标签的两种使用方法
  3. HibernateTemplate、HibernateDaoSupport两种方法实现增删改查Good
  4. 图像相似度测量与模板匹配总结
  5. 使用ResourceBundle加载properties文件
  6. [单选题]$array = array('a','b','c','d'); $array_now = array_splice($array,2); print_r($array_now);...
  7. 与JBoss Fuse,Jenkins和Nexus的持续集成
  8. python缺失值填充均值法_pandas 使用均值填充缺失值列的小技巧分享
  9. MeEdu - 开源在线教育点播系统。
  10. 遇见C++ Lambda
  11. linux查看进程加载的jar包,[Linux] 查看jar包内容
  12. linux内核符号地址,Linux内核-模块专用地址空间
  13. 帝国CMS7.5仿可可礼物网漂亮大气淘宝客网站源码 带手机版+火车头采集
  14. 抖音下载android,抖音完整版
  15. Nik插件滤镜套装Nik Collection 3 Mac
  16. JUC并发编程基石AQS源码之结构篇-ReentrantLock
  17. Matplotlib常见图形绘制(折线图、散点图 、柱状图 、直方图 、饼图 、条形图)
  18. 给在读研究生+未来要读研同学们的一封受益匪浅的信
  19. 2019全国计算机模拟题,2019年全国计算机二级Java考试模拟习题3
  20. VMware虚拟机+Kali linux 2021.2 下载和安装以及初始操作

热门文章

  1. 一篇合格的新闻稿由哪5部分构成?
  2. 亚商投资顾问早餐FM/0324互联网医疗迎利好
  3. 外贸财务ERP管理软件丨汇信外贸软件
  4. N皇后问题分析与求解算法图解、流程图和复杂度
  5. matlab 没有normcdf,Matlab 中标准 正态分布的密度函数是 normcdf(x,0,1) 。
  6. Linux之高级网络配置(bond,team以及网桥的搭建)
  7. android多个水波球,Android最简单的方式实现波浪纹和小球
  8. Python-神秘图案
  9. python俄罗斯方块实训报告_用 Python 写个俄罗斯方块
  10. hadoop hdfs常见命令