JSch Shell通道在继续之前逐个执行命令测试结果

我有一个连接SSH shell的程序。 我能够执行命令并从中读取输出。

但我有一个新的要求。 现在,如果成功执行下一个命令,我需要执行命令并读取输出。

我使用过这个问题的程序: JSch问题 – 无法检索完整的命令输出

public class SshConnectionManager { private static Session session; private static ChannelShell channel; private static String username = ""; private static String password = ""; private static String hostname = ""; private static Session getSession(){ if(session == null || !session.isConnected()){ session = connect(hostname,username,password); } return session; } private static Channel getChannel(){ if(channel == null || !channel.isConnected()){ try{ channel = (ChannelShell)getSession().openChannel("shell"); channel.setPty(false); channel.connect(); }catch(Exception e){ System.out.println("Error while opening channel: "+ e); } } return channel; } private static Session connect(String hostname, String username, String password){ JSch jSch = new JSch(); try { session = jSch.getSession(username, hostname, 22); Properties config = new Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); session.setPassword(password); System.out.println("Connecting SSH to " + hostname + " - Please wait for few seconds... "); session.connect(); System.out.println("Connected!"); }catch(Exception e){ System.out.println("An error occurred while connecting to "+hostname+": "+e); } return session; } private static void executeCommands(List commands){ try{ Channel channel=getChannel(); System.out.println("Sending commands..."); sendCommands(channel, commands); readChannelOutput(channel); System.out.println("Finished sending commands!"); }catch(Exception e){ System.out.println("An error ocurred during executeCommands: "+e); } } private static void sendCommands(Channel channel, List commands){ try{ PrintStream out = new PrintStream(channel.getOutputStream()); out.println("#!/bin/bash"); for(String command : commands){ out.println(command); } out.println("exit"); out.flush(); }catch(Exception e){ System.out.println("Error while sending commands: "+ e); } } private static void readChannelOutput(Channel channel){ byte[] buffer = new byte[1024]; try{ InputStream in = channel.getInputStream(); String line = ""; while (true){ while (in.available() > 0) { int i = in.read(buffer, 0, 1024); if (i < 0) { break; } line = new String(buffer, 0, i); System.out.println(line); } if(line.contains("logout")){ break; } if (channel.isClosed()){ break; } try { Thread.sleep(1000); } catch (Exception ee){} } }catch(Exception e){ System.out.println("Error while reading channel output: "+ e); } } public static void close(){ channel.disconnect(); session.disconnect(); System.out.println("Disconnected channel and session"); } public static void main(String[] args){ List commands = new ArrayList(); commands.add("ls -l"); executeCommands(commands); close(); } } 

我需要使用“shell”通道而不是“exec”,因为服务器不允许“exec”通道: http : //www.tembria.com/forums/viewtopic.php? t = 477&sid = 8f2a82ec30e89ba44d184a3b2a65ec69

通常,您应该使用“exec”通道。 “shell”通道不应用于自动执行命令。

但我知道您的服务器不支持“exec”频道。 我已经为其他读者添加了上述评论,而不是尝试使用此解决方案,除非他们确实需要。


正如@Yair Harel已经评论过的,如果你必须使用“shell”通道,你必须使用shell技术。

因此,在您的特定情况下,您可能希望远程shell在命令完成后打印一些唯一的字符串和退出代码:

 out.println(command + " ; echo Command-has-finished-with-code-$?"); 

然后你继续阅读输出,直到找到一行开头"Command-has-finished-with-code-" 。 您解析退出代码并决定如何继续。

请注意,命令语法(特别是命令分隔符;以及退出代码变量$? )是特定于操作系统和shell的。 由于您的服务器不是标准类型,因此语法可能不同。


附注:

  • "#!/bin/bash"是一个纯粹的废话。 shell忽略所有以#开头的命令(它的注释)。 发送它没有意义。
  • 不要使用StrictHostKeyChecking=no 。 使用session.setConfig(“StrictHostKeyChecking”,“no”)查看JSch SFTP安全性;