Jsch – 一个会话多个频道

我设法通过ssh用Jsch执行单个命令但是当我尝试执行第二个命令时它失败了

为了调试我把这个问题归结为这样:

import java.io.IOException; import java.io.InputStream; import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelExec; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; public class Exec { public static void test(Session session) throws Exception { Channel channel = session.openChannel("exec"); ((ChannelExec) channel).setCommand("pwd"); channel.setInputStream(null); ((ChannelExec) channel).setErrStream(System.err); InputStream in = channel.getInputStream(); channel.connect(); 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()) { System.out.println("exit-status: " + channel.getExitStatus()); break; } try { Thread.sleep(1000); } catch (Exception ee) { } } channel.disconnect(); } public static void main(String[] arg) { try { JSch jsch = new JSch(); Session session = jsch.getSession("nck", "127.0.0.1", 22); session.setPassword("asd"); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); test(session); // This one succeeds with exit-status: 0 test(session); // This one fails with exit-status: 255 session.disconnect(); } catch (Exception e) { // } } } 

这主要是官方的Exec示例,但这给了我这个输出:

 /home/nck exit-status: 0 exit-status: 255 

第一个命令成功执行第二个不执行。

有任何想法吗 ?

嘿我和jsch和Ubuntu有完全相同的问题。 (怎么样)你解决了吗? 为每次执行创建一个新会话会占用太多时间吗? 目前我捕获了jschexception并搜索“session is not down”然后我重新连接会话并再次执行命令。 这有效,但不是一个好的解决方案。

编辑:我错了,我现在通过使用解决了我的问题

channel = session.openChannel("shell");

而不是“exec”。

这是一个基于@krishna答案的完整工作Java类:

 /** * Run several ssh commands in a single JSch session */ import com.jcraft.jsch.Channel; import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; import java.io.*; class SshMultiCommands { public static void main(String[] args) throws Exception { JSch jsch = new JSch(); String user = "user"; //CHANGE ME String host = "192.168.222.157"; //CHANGE ME String passwd = "password"; //CHANGE ME int port = 22; Session session = jsch.getSession(user, host, port); session.setPassword(passwd); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); Channel channel = session.openChannel("shell"); OutputStream ops = channel.getOutputStream(); PrintStream ps = new PrintStream(ops, true); channel.connect(); InputStream input = channel.getInputStream(); //commands ps.println("ls -lag"); ps.println("cd /etc"); ps.println("ls"); ps.println("exit"); ps.close(); printResult(input, channel); channel.disconnect(); session.disconnect(); } /** * @param input * @param channel */ private static void printResult(InputStream input, Channel channel) throws Exception { int SIZE = 1024; byte[] tmp = new byte[SIZE]; while (true) { while (input.available() > 0) { int i = input.read(tmp, 0, SIZE); if(i < 0) break; System.out.print(new String(tmp, 0, i)); } if(channel.isClosed()) { System.out.println("exit-status: " + channel.getExitStatus()); break; } try { Thread.sleep(300); } catch (Exception ee) { } } } } 

你可以使用shell来执行多个命令。 以下是通过shell执行命令的代码。

 Channel channel=session.openChannel("shell"); OutputStream ops = channel.getOutputStream(); PrintStream ps = new PrintStream(ops, true); channel.connect(); ps.println("mkdir folder"); ps.println("dir"); //give commands to be executed inside println.and can have any no of commands sent. ps.close(); InputStream in=channel.getInputStream(); byte[] bt=new byte[1024]; while(true) { while(in.available()>0) { int i=in.read(bt, 0, 1024); if(i<0) break; String str=new String(bt, 0, i); //displays the output of the command executed. System.out.print(str); } if(channel.isClosed()) break; Thread.sleep(1000); channel.disconnect(); session.disconnect(); } 

我使用了完全相同的代码,并且有时会读取通过ssh执行的脚本输出的问题。 有时程序缺少所有内容,有时只缺少部分内容。 我通过更改嵌套循环中的if(channel.isclosed)解决了我的问题。 这是新代码

 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) { int i = in.read(tmp, 0, 1024); System.out.print(new String(tmp, 0, i)); } System.out.println("exit-status: " + channel.getExitStatus()); break; } try { Thread.sleep(1000); } catch (Exception ee) { } 

如果你想使用exec。 您可以通过在命令中放置一个分号(;)来运行多个命令

喜欢:

 pwd;ls- -l; cd foldername ((ChannelExec) channel).setCommand("pwd;ls -l; cd foldername"); 

这不是jsch中的错误,它是我的ssh服务器的一个错误(cygwin – 我打赌我配置错了……)

编辑:嗯我与Ubuntu的jsch有同样的问题……很奇怪

猜测是workarround我将不得不为每个查询打开一个新的会话。