如何在String中获取jsch shell命令输出

我使用JSCH -SSH库在“shell”通道中执行命令,但无法找到办法做两件事: –

1)如何查找命令是否在远程unix盒上完全执行?

2)如何捕获String中的命令输出,而不是在System.out控制台上打印它?

下面是我的代码片段,可以在system.out上显示shell命令输出

注意:我不想使用“exec”通道,因为它为每个命令启动一个新进程,并且不记得导出的“会话”变量。 我必须使用“shell”频道。

下面是我的代码片段。 任何帮助表示赞赏。谢谢你的时间。

try{ String commandToRun = "ls /tmp/*.log \n"; if(channel.isClosed()) channel=session.openChannel("shell"); byte[] bytes = commandToRun.getBytes(); ByteArrayInputStream bais=new ByteArrayInputStream(bytes); channel.setInputStream(bais); InputStream ins=channel.getInputStream(); channel.connect(); channel.setOutputStream(System.out);//This prints on console. Need 2 capture in String somehow? //in-efficient way to allow command to execute completely on remote Unix machine //DO NOT know a better way, to know when command is executed completely Thread.sleep(5000L); } catch(Exception e){ System.out.println("Exception in executeCommand() --->"+ e.getMessage()); e.printStackTrace(); } 

2)你可以使用ByteArrayOutputStream

 final ByteArrayOutputStream baos = new ByteArrayOutputStream(); channel.setOutputStream(baos); 

然后从new String(baos.toByteArray())创建新字符串

对于1,您是否尝试在命令结束时使用2>&1?

 String commandToRun = "ls /tmp/*.log 2>&1 \n"; 

对于OP,可能不再需要我的解决方案,但是正在寻找解决方案以覆盖两种情况的任何其他人1)等待命令在远程机器上完成; 2)将输出捕获为字符串; 你可以试试这个:

 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.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(); } } 

如果您需要一次发送多个命令并保持通道打开以便以后重复使用,此解决方案也很有用。

以Mihail提供的示例,关于互联网的其他信息以及Martin的反馈为例,这是使用exec的重写解决方案。 请注意,打开会话允许发送多个命令,每个命令打开它自己的输入/输出通道。

Rant :我真的不喜欢让进程’ OUTPUT流写入。 多么烦人的范例(至少对我而言)。 我想要的是将输出写入的进程输入流,并且有一个非常困难的时间来计算它是倒置的。 它只是我还是以下(伪代码)没有让路更有意义?

channel.getInputStream().write("here's some text to write into my channel.");

String ret = channel.getOutputStream().getOutput();

无论如何,感谢Mihail和Martin的评论/意见。

 public class SSHConnectionManager { private Session session; private String username = "user"; private String password = "password"; private String hostname = "myhost"; public SSHConnectionManager() { } public SSHConnectionManager(String hostname, String username, String password) { this.hostname = hostname; this.username = username; this.password = password; } public void open() throws JSchException { open(this.hostname, this.username, this.password); } public void open(String hostname, String username, String password) throws JSchException{ JSch jSch = new JSch(); session = jSch.getSession(username, hostname, 22); Properties config = new Properties(); config.put("StrictHostKeyChecking", "no"); // not recommended session.setConfig(config); session.setPassword(password); System.out.println("Connecting SSH to " + hostname + " - Please wait for few seconds... "); session.connect(); System.out.println("Connected!"); } public String runCommand(String command) throws JSchException, IOException { String ret = ""; if (!session.isConnected()) throw new RuntimeException("Not connected to an open session. Call open() first!"); ChannelExec channel = null; channel = (ChannelExec) session.openChannel("exec"); channel.setCommand(command); channel.setInputStream(null); PrintStream out = new PrintStream(channel.getOutputStream()); InputStream in = channel.getInputStream(); // channel.getInputStream(); channel.connect(); // you can also send input to your running process like so: // String someInputToProcess = "something"; // out.println(someInputToProcess); // out.flush(); ret = getChannelOutput(channel, in); channel.disconnect(); System.out.println("Finished sending commands!"); return ret; } private String getChannelOutput(Channel channel, InputStream in) throws IOException{ byte[] buffer = new byte[1024]; StringBuilder strBuilder = new StringBuilder(); String line = ""; while (true){ while (in.available() > 0) { int i = in.read(buffer, 0, 1024); if (i < 0) { break; } strBuilder.append(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){} } return strBuilder.toString(); } public void close(){ session.disconnect(); System.out.println("Disconnected channel and session"); } public static void main(String[] args){ SSHConnectionManager ssh = new SSHConnectionManager(); try { ssh.open(); String ret = ssh.runCommand("ls -l"); System.out.println(ret); ssh.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }