使用Jsch执行Shell脚本

来源:互联网 发布:cf手游外卦软件 编辑:程序博客网 时间:2024/05/29 16:17

首发CSDN http://blog.csdn.net/basecn/archive/2010/12/16/6080741.aspx

作者: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,在控制台看到结果,只是无法保存下来。

[java] view plaincopy
  1. FileOutputStream fileOut = new FileOutputStream( outputFileName );  
  2. channelShell.setOutputStream( fileOut );  
 

输入

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

[java] view plaincopy
  1. PipedInputStream pipeIn = new PipedInputStream();  
  2. PipedOutputStream pipeOut = new PipedOutputStream( pipeIn );  
  3. 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端就认为是一条完整命令了。很奇怪的特性!

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

附上类代码

[java] view plaincopy
  1. package jsch;  
  2.   
  3. import static java.lang.String.format;  
  4. import java.io.Closeable;  
  5. import java.io.FileOutputStream;  
  6. import java.io.IOException;  
  7. import java.io.InputStream;  
  8. import java.io.PipedInputStream;  
  9. import java.io.PipedOutputStream;  
  10. import com.jcraft.jsch.ChannelExec;  
  11. import com.jcraft.jsch.ChannelShell;  
  12. import com.jcraft.jsch.JSch;  
  13. import com.jcraft.jsch.Session;  
  14. import com.jcraft.jsch.UserInfo;  
  15. import com.nsm.hermes.wand.Wand;  
  16. public class SshExecuter  
  17.     implements Closeable{  
  18.     static long interval = 1000L;  
  19.     static int timeout = 3000;  
  20.     private SshInfo sshInfo = null;  
  21.     private JSch jsch = null;  
  22.     private Session session = null;  
  23.   
  24.     private SshExecuter( SshInfo info ) throws Exception{  
  25.         sshInfo = info;  
  26.         jsch = new JSch();  
  27.         jsch.addIdentity( sshInfo.getKey() );  
  28.         session = jsch.getSession(  sshInfo.getUser(),  
  29.                                     sshInfo.getHost(),  
  30.                                     sshInfo.getPort() );  
  31.         UserInfo ui = new SshUserInfo( sshInfo.getPassPhrase() );  
  32.         session.setUserInfo( ui );  
  33.         session.connect();  
  34.     }  
  35.     public long shell( String cmd, String outputFileName )  
  36.         throws Exception{  
  37.         long start = System.currentTimeMillis();  
  38.         ChannelShell channelShell = (ChannelShell)session.openChannel( "shell" );  
  39.         PipedInputStream pipeIn = new PipedInputStream();  
  40.         PipedOutputStream pipeOut = new PipedOutputStream( pipeIn );  
  41.         FileOutputStream fileOut = new FileOutputStream( outputFileName );  
  42.         channelShell.setInputStream( pipeIn );  
  43.         channelShell.setOutputStream( fileOut );  
  44.         channelShell.connect( timeout );  
  45.         pipeOut.write( cmd.getBytes() );  
  46.         Thread.sleep( interval );  
  47.         pipeOut.close();  
  48.         pipeIn.close();  
  49.         fileOut.close();  
  50.         channelShell.disconnect();  
  51.         return System.currentTimeMillis() - start;  
  52.     }  
  53.     public int exec( String cmd )  
  54.         throws Exception{  
  55.         ChannelExec channelExec = (ChannelExec)session.openChannel( "exec" );  
  56.         channelExec.setCommand( cmd );  
  57.         channelExec.setInputStream( null );  
  58.         channelExec.setErrStream( System.err );  
  59.         InputStream in = channelExec.getInputStream();  
  60.         channelExec.connect();  
  61.         int res = -1;  
  62.         StringBuffer buf = new StringBuffer( 1024 );  
  63.         byte[] tmp = new byte1024 ];  
  64.         while ( true ) {  
  65.             while ( in.available() > 0 ) {  
  66.                 int i = in.read( tmp, 01024 );  
  67.                 if ( i < 0 ) break;  
  68.                 buf.append( new String( tmp, 0, i ) );  
  69.             }  
  70.             if ( channelExec.isClosed() ) {  
  71.                 res = channelExec.getExitStatus();  
  72.                 System.out.println( format( "Exit-status: %d", res ) );  
  73.                 break;  
  74.             }  
  75.             Wand.waitA( 100 );  
  76.         }  
  77.         System.out.println( buf.toString() );  
  78.         channelExec.disconnect();  
  79.         return res;  
  80.     }  
  81.     public static SshExecuter newInstance()  
  82.         throws Exception{  
  83.         String host = "localhost";  
  84.         Integer port = 22;  
  85.         String user = "hadoop";  
  86.         String key = "./id_dsa";  
  87.         String passPhrase = "";  
  88.         SshInfo i = new SshInfo( host, port, user, key, passPhrase );  
  89.         return new SshExecuter( i );  
  90.     }  
  91.     public Session getSession(){  
  92.         return session;  
  93.     }  
  94.     public void close()  
  95.         throws IOException{  
  96.         getSession().disconnect();  
  97.     }  
  98. }  
  99.   
  100. class SshInfo{  
  101.     String host = null;  
  102.     Integer port = 22;  
  103.     String user = null;  
  104.     String key = null;  
  105.     String passPhrase = null;  
  106.     public SshInfo( String host,  
  107.                     Integer port,  
  108.                     String user,  
  109.                     String key,  
  110.                     String passPhrase ){  
  111.         super();  
  112.         this.host = host;  
  113.         this.port = port;  
  114.         this.user = user;  
  115.         this.key = key;  
  116.         this.passPhrase = passPhrase;  
  117.     }  
  118.     public String getHost(){  
  119.         return host;  
  120.     }  
  121.     public Integer getPort(){  
  122.         return port;  
  123.     }  
  124.     public String getUser(){  
  125.         return user;  
  126.     }  
  127.     public String getKey(){  
  128.         return key;  
  129.     }  
  130.     public String getPassPhrase(){  
  131.         return passPhrase;  
  132.     }  
  133. }  
  134.   
  135. class SshUserInfo implements UserInfo{  
  136.       
  137.     private String passphrase = null;  
  138.     public SshUserInfo( String passphrase ){  
  139.         super();  
  140.         this.passphrase = passphrase;  
  141.     }  
  142.     public String getPassphrase(){  
  143.         return passphrase;  
  144.     }  
  145.     public String getPassword(){  
  146.         return null;  
  147.     }  
  148.     public boolean promptPassphrase( String pass ){  
  149.         return true;  
  150.     }  
  151.     public boolean promptPassword( String pass ){  
  152.         return true;  
  153.     }  
  154.     public boolean promptYesNo( String arg0 ){  
  155.         return true;  
  156.     }  
  157.     public void showMessage( String m ){  
  158.         System.out.println( m );  
  159.     }  
  160. }  
0 0
原创粉丝点击