java jsch 调用shell_使用Jsch执行Shell脚本
作者: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脚本相关推荐
- python 执行shell_从python执行Shell脚本与变量
我有这个代码: opts.info("Started domain %s (id=%d)" % (dom,domid)) 我想从上面执行一个带有参数domid的shell脚本. 这 ...
- Windows IEDA 编译Hbase源码报错 - 无法执行shell脚本
windows 下编译 hbase源码,报错 [ERROR] Command execution failed. java.io.IOException: Cannot run program &qu ...
- java 调用casperjs_Java程序去调用并执行shell脚本及问题总结(推荐)
摘要: 该文章来自阿里巴巴技术协会(ATA)精选集 背景 我们在开发过程中,大部分是java开发, 而在文本处理过程中,主要就是脚本进行开发. java开发的特点就是我们可以很早地进行TDDL, ME ...
- 脚本运行显示服务器超时,java执行shell脚本超时
java执行shell脚本超时 [2021-02-11 04:20:34] 简介: 系统运维 在数据库运维的过程中,Shell 脚本在很大程度上为运维提供了极大的便利性.而shell 脚本参数作为变 ...
- python调用shell脚本的参数_使用python执行shell脚本 并动态传参 及subprocess的使用详解
最近工作需求中 有遇到这个情况 在web端获取配置文件内容 及 往shell 脚本中动态传入参数 执行shell脚本这个有多种方法 最后还是选择了subprocess这个python标准库 subpr ...
- Java程序定时执行shell脚本
第一次写博客,写的不好还请见谅. 之前在Linux环境中想定期执行某个脚本,第一反应就是将这个task加入到crontab里(crontab的知识点这里就不具体介绍了),当然,这种做法一般情况下是可行 ...
- java执行shell脚本 process.waitFor()返回1
记录一下今天遇到的一个问题 在java代码中执行shell脚本,部分代码如下 Process p = null; List<String> cmds = new ArrayList< ...
- 运维经验分享(六)-- 深究crontab不能正确执行Shell脚本的问题(二)
运维经验分享作为一个专题,目前共7篇文章 <运维经验分享(一)-- Linux Shell之ChatterServer服务控制脚本> <运维经验分享(二)-- Linux Shell ...
- Linux中执行shell脚本的4种方法
这篇文章主要介绍了Linux中执行shell脚本的4种方法总结,即在Linux中运行shell脚本的4种方法,需要的朋友可以参考下. bash shell 脚本的方法有多种,现在作个小结.假设我们编写 ...
最新文章
- 【C++】Google C++编码规范(一):作用域
- HTML5中aside标签的两种使用方法
- HibernateTemplate、HibernateDaoSupport两种方法实现增删改查Good
- 图像相似度测量与模板匹配总结
- 使用ResourceBundle加载properties文件
- [单选题]$array = array('a','b','c','d'); $array_now = array_splice($array,2); print_r($array_now);...
- 与JBoss Fuse,Jenkins和Nexus的持续集成
- python缺失值填充均值法_pandas 使用均值填充缺失值列的小技巧分享
- MeEdu - 开源在线教育点播系统。
- 遇见C++ Lambda
- linux查看进程加载的jar包,[Linux] 查看jar包内容
- linux内核符号地址,Linux内核-模块专用地址空间
- 帝国CMS7.5仿可可礼物网漂亮大气淘宝客网站源码 带手机版+火车头采集
- 抖音下载android,抖音完整版
- Nik插件滤镜套装Nik Collection 3 Mac
- JUC并发编程基石AQS源码之结构篇-ReentrantLock
- Matplotlib常见图形绘制(折线图、散点图 、柱状图 、直方图 、饼图 、条形图)
- 给在读研究生+未来要读研同学们的一封受益匪浅的信
- 2019全国计算机模拟题,2019年全国计算机二级Java考试模拟习题3
- VMware虚拟机+Kali linux 2021.2 下载和安装以及初始操作
热门文章
- 一篇合格的新闻稿由哪5部分构成?
- 亚商投资顾问早餐FM/0324互联网医疗迎利好
- 外贸财务ERP管理软件丨汇信外贸软件
- N皇后问题分析与求解算法图解、流程图和复杂度
- matlab 没有normcdf,Matlab 中标准 正态分布的密度函数是 normcdf(x,0,1) 。
- Linux之高级网络配置(bond,team以及网桥的搭建)
- android多个水波球,Android最简单的方式实现波浪纹和小球
- Python-神秘图案
- python俄罗斯方块实训报告_用 Python 写个俄罗斯方块
- hadoop hdfs常见命令