通过JSch shell通道向服务器发送命令

我无法弄清楚如何通过JSch shell通道发送命令。

我这样做,但它不起作用:

JSch shell = new JSch(); String command = "cd home/s/src"; Session session = shell.getSession(username, host, port); MyUserInfo ui = new MyUserInfo(); ui.setPassword(password); session.setUserInfo(ui); session.connect(); channel = session.openChannel("shell"); fromServer = new BufferedReader(new InputStreamReader(channel.getInputStream())); toServer = channel.getOutputStream(); channel.connect(); toServer.write((command + "\r\n").getBytes()); toServer.flush(); 

然后我读取这样的输入:

 StringBuilder builder = new StringBuilder(); int count = 0; String line = ""; while(line != null) { line = fromServer.readLine(); builder.append(line).append("\n"); if (line.endsWith(".") || line.endsWith(">")){ break; } } String result = builder.toString(); ConsoleOut.println(result); 

如果它挂起在readLine() ,这意味着你的“while”永远不会结束(可能不太可能考虑你的代码),或者, readLine()正在等待它的源,即IOstream阻塞线程原因available()!=true

如果没有看到您的调试信息,我无法完全解决您的代码问题。 但作为建议,你试过PipedIntputStream吗? 我们的想法是将您的控制台输入传递给“您的”输出,以便您可以“写”它。 要实现这一点,您需要初始化输入/输出。

 InputStream in = new PipedInputStream(); PipedOutputStream pin = new PipedOutputStream((PipedInputStream) in); /**...*/ channel.setInputStream(in); channel.connect(); /** ...*/ pin.write(myScript.getBytes()); 

您的问题也是如此,如何读取控制台输出。

 PipedInputStream pout = new PipedInputStream((PipedOutputStream) out); /** * ... */ BufferedReader consoleOutput = new BufferedReader(new InputStreamReader(pout)); consoleOutput.readLine(); 

而且,如果您不确定要读取多少行并因此想要使用“while”,请确保在内部执行某些操作以防止1)忙等待2)结束条件。 例:

 while(!end) { consoleOutput.mark(32); if (consoleOutput.read()==0x03) end = true;//End of Text else { consoleOutput.reset(); consoleOutput.readLine(); end = false; } } 

尝试这个:

 JSch jsch = new JSch(); try { Session session = jsch.getSession("root", "192.168.0.1", 22); java.util.Properties config = new java.util.Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); session.connect(); String command = "lsof -i :80"; Channel channel = session.openChannel("exec"); ((ChannelExec) channel).setCommand(command); 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(); session.disconnect(); } catch (Exception e) { System.out.println(e.getMessage()); } 
 private void executeRemoteCommandAsSudo(String sudoAs, String password, String command, int delayInSeconds) { logger.info("executeRemoteCommandAsSudo started...."); logger.info("sudoAs=" + sudoAs); logger.info("command=" + command); logger.info("delayInSeconds=" + delayInSeconds); Session session = null; Channel channel = null; try { session = getSession(); channel = session.openChannel("exec"); String sudoCommand = "sudo su - " + sudoAs; ((ChannelExec) channel).setCommand(sudoCommand); ((ChannelExec) channel).setPty(true); channel.connect(); InputStream inputStream = channel.getInputStream(); OutputStream out = channel.getOutputStream(); ((ChannelExec) channel).setErrStream(System.err); out.write((password + "\n").getBytes()); out.flush(); Thread.sleep(1000); out.write((command + "\n").getBytes()); out.flush(); Thread.sleep(1000 * delayInSeconds); out.write(("logout" + "\n").getBytes()); out.flush(); Thread.sleep(1000); logInfo(channel, inputStream); out.write(("exit" + "\n").getBytes()); out.flush(); out.close(); Thread.sleep(1000); } catch (Exception ex) { logger.error(ex.getMessage()); } finally { session.disconnect(); channel.disconnect(); } logger.info("executeRemoteCommandAsSudo completed...."); } private void logInfo(Channel channel, InputStream in) { try { byte[] tmp = new byte[1024]; while (true) { while (in.available() > 0) { int i = in.read(tmp, 0, 1024); if (i < 0) break; logger.info(new String(tmp, 0, i)); } if (channel.isClosed()) { logger.info("exit-status: " + channel.getExitStatus()); break; } } } catch (Exception ex) { logger.error(ex); } } private Session getSession() throws JSchException { JSch jsch = new JSch(); logger.info("ftpUser=" + ftpUser); logger.info("ftpHost=" + ftpHost); Session session = jsch.getSession(ftpUser, ftpHost, 22); session.setPassword(ftpPassword); java.util.Properties config = new java.util.Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); session.connect(); return session; } 

以下是我的任务的快速编写代码。 不是一个做得好的计划。 但是服务于它的目的。

  1. 通过SSH(使用Jsch)连接到服务器(使用私钥文件 – mykey.pem)
  2. 创建一个shell脚本(用于挂载卷和mkfs)
  3. 在远程计算机上运行
  4. 你可以在stdout上看到输出

代码如下:

 public class connectSSH { public void connect(String dnsName, String privKey) throws IOException { JSch jSch = new JSch(); try { //Authenticate through Private Key File jSch.addIdentity(privKey); //Give the user and dnsName Session session = jSch.getSession("root", dnsName, 22); //Required if not a trusted host java.util.Properties config = new java.util.Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); System.out.println("Connecting SSH to " + dnsName + " - Please wait for few minutes... "); session.connect(); //Open a shell Channel channel=session.openChannel("shell"); channel.setOutputStream(System.out); //Create a Shell Script File shellScript = createShellScript(); //Convert the shell script to byte stream FileInputStream fin = new FileInputStream(shellScript); byte fileContent[] = new byte[(int)shellScript.length()]; fin.read(fileContent); InputStream in = new ByteArrayInputStream(fileContent); //Set the shell script to the channel as input stream channel.setInputStream(in); //Connect and have fun! channel.connect(); } catch (JSchException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public File createShellScript() { String filename = "shellscript.sh"; File fstream = new File(filename); try{ // Create file PrintStream out = new PrintStream(new FileOutputStream(fstream)); out.println("#!/bin/bash"); out.println("echo \"hi\" > /tmp/test.info"); out.println("echo \"n\" > /tmp/fdisk.in"); out.println("echo \"p\" >> /tmp/fdisk.in"); out.println("echo \"1\" >> /tmp/fdisk.in"); out.println("echo >> /tmp/fdisk.in"); out.println("echo >> /tmp/fdisk.in"); out.println("echo \"w\" >> /tmp/fdisk.in"); out.println("/sbin/fdisk /dev/sdf < /tmp/fdisk.in"); out.println("mkfs.ext3 /dev/sdf1"); out.println("mkdir /usr/myebs"); out.println("mount /dev/sdf1 /usr/myebs"); out.println("partprobe /dev/sdf1"); out.println("echo \"Success\""); //Close the output stream out.close(); }catch (Exception e){//Catch exception if any System.err.println("Error: " + e.getMessage()); } return fstream; } public static void main(String[] args) { connectSSH ssh = new connectSSH(); String privKey = "/Users/neo/Desktop/mykey.pem"; try { ssh.connect("yourexampleserver.com", privKey); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 

使用管道输入和输出流似乎很有趣:

 JSch jsch = new JSch(); jsch.addIdentity("/home/audrius/.ssh/blablabla", "blablablabla"); String user = "audrius"; String host = "ultrastudio.org"; Session session = jsch.getSession(user, host, 439); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); Channel channel = session.openChannel("shell"); PipedInputStream pip = new PipedInputStream(40); channel.setInputStream(pip); PipedOutputStream pop = new PipedOutputStream(pip); PrintStream print = new PrintStream(pop); channel.setOutputStream(System.out); print.println("ls"); 

尝试这个

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

我意识到这是一个老线程,但我今天遇到了类似的问题。 这是我的解决方案。

 public class ChannelConsole { // ================================================ // static fields // ================================================ // ================================================ // instance fields // ================================================ private Session session; // ================================================ // constructors // ================================================ public ChannelConsole(Session session) { this.session = session; } // ================================================ // getters and setters // ================================================ // ================================================ // public methods // ================================================ public String execute(String command) throws JSchException { command = command.trim() + "\n"; ChannelExec channel = (ChannelExec) this.session.openChannel("exec"); channel.setCommand(command); ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); channel.setOutputStream(responseStream); channel.connect(); try { awaitChannelClosure(channel); } catch (InterruptedException e) { // no one cares } String result = responseStream.toString(); closeQuietly(responseStream); return result; } // ================================================ // private methods // ================================================ private void awaitChannelClosure(ChannelExec channel) throws InterruptedException { while (channel.isConnected()) { Thread.sleep(100); } } private static void closeQuietly(Closeable closeable) { if (closeable == null) { return; } try { closeable.close(); } catch (IOException ignored) { ignored.printStackTrace(); } } } 

使用这个类你可以做类似的事情: shell = new ChannelConsole(this.session); String result = shell.execute("quota -v; echo; echo \"Disk storage information:\"; df -hk") shell = new ChannelConsole(this.session); String result = shell.execute("quota -v; echo; echo \"Disk storage information:\"; df -hk")

用法:

 String remoteCommandOutput = exec("ssh://user:pass@host/work/dir/path", "ls -t | head -n1"); String remoteShellOutput = shell("ssh://user:pass@host/work/dir/path", "ls") shell("ssh://user:pass@host/work/dir/path", "ls", System.out) shell("ssh://user:pass@host", System.in, System.out); 

履行

试试这段代码:

  JSch jsch=new JSch(); System.out.println("Getting session"); Session session=jsch.getSession("root","10.0.0.0",22); System.out.println("session is ::::"+session.getHost()); // username and password will be given via UserInfo interface. UserInfo ui = new MyUserInfo("Lab@123", null); //UserInfo ui = new MyUserInfo(password, null); session.setUserInfo(ui); session.setPassword("Lab@123"); Properties config = new java.util.Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); session.connect(40000); Channel channel=session.openChannel("exec"); ((ChannelExec)channel).setCommand("ls"); channel.connect(); channel.run(); // get I/O streams for remote scp OutputStream out=channel.getOutputStream(); InputStream in=channel.getInputStream(); String output=""; while (channel.isClosed()!=true) { try { output+=streamToString(in); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("Output is :::"+output); channel.disconnect(); session.disconnect(); } public static String streamToString(InputStream input)throws Exception { String output = ""; while(input.available()>0) { output += ((char)(input.read())); } return output; } public static OutputStream stringToStream(String charset) throws IOException{ byte[] bytes = charset.getBytes(); /*ByteArrayInputStream bais = new ByteArrayInputStream(bytes); InputStreamReader isr = new InputStreamReader(bais);*/ InputStream is = null; OutputStream os = null; try { is = new ByteArrayInputStream(charset.getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } //byte[] buf = new byte[1024]; int numRead; while ( (numRead = is.read(bytes) ) >= 0) { os.write(bytes, 0, numRead); } return os;