我正在使用JSCH -SSH库在“ shell”通道中执行命令,但找不到找到两种方法的方法:
1)如何查找命令是否在远程unix box上完全执行?
2)如何在String中捕获命令输出,而不是在System.out控制台上打印它?
下面是我的代码片段,可以在system.out上显示shell命令输出
注意:我不想使用“ exec”通道,因为它为每个命令启动一个新进程,并且不记得已导出的“ session”变量。我必须使用“ 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
ByteArrayOutputStream
final ByteArrayOutputStream baos = new ByteArrayOutputStream(); channel.setOutputStream(baos);
然后从创建新字符串 new String(baos.toByteArray())
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<String> 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<String> 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<String> commands = new ArrayList<String>(); commands.add("ls -l"); executeCommands(commands); close(); } }
如果您需要一次发送多个命令并保持通道打开以供以后使用,则此解决方案也很有用。