2014-03-07 77 views
2

我想通过我的java程序在ssh上执行多个命令。基于执行结果,我需要在同一个shell上执行一些更多的命令。但是当我试图执行它正在采取不同的外壳。如果有人知道这个决议是非常赞赏的。如何使用相同的shell通过JSCH执行多个unix命令?

这里是我的代码片段

public class sshconnectionTest { 
    JSch jsch = new JSch(); 
    Session session; 
    Channel channel; 

    public Session openSession() throws Exception { 

     if (null == session) { 
      session = jsch.getSession("user", "hostname", 
        22); 

      System.out.println("**************************************" 
        + session.isConnected()); 

      AESencrp aesEncrypt = new AESencrp(); 

      session.setPassword("pwd"); 
      session.setConfig("StrictHostKeyChecking", "no"); 
      session.connect(10 * 1000); 

     } 
     return session; 
    } 

    public Channel openChannel(Session session) throws Exception { 

     if (null == channel) { 
      channel = session.openChannel("exec"); 
     } 

     return channel; 
    } 

    public String getSession(String command1) throws Exception { 

     try { 

      session = openSession(); 
      channel = openChannel(session); 

      Channel channel = session.openChannel("exec"); 
      ((ChannelExec) channel).setCommand(command1); 
      channel.setInputStream(null); 
      ((ChannelExec) channel).setErrStream(System.err); 

      InputStream in = channel.getInputStream(); 
      channel.connect(); 
      byte[] tmp = new byte[1024]; 
      String readText = ""; 
      while (true) { 
       while (in.available() > 0) { 
        int i = in.read(tmp, 0, 1024); 
        if (i < 0) 
         break; 
        readText = new String(tmp, 0, i); 

        System.out.print(readText); 
       } 
       if (channel.isClosed()) { 
        System.out.println("exit-status: " 
          + channel.getExitStatus()); 
        break; 
       } 
       try { 
        Thread.sleep(1000); 
       } catch (Exception ee) { 
       } 
      } 
      channel.disconnect(); 
      // session.disconnect(); 
      System.out.println("DONE"); 

     } catch (Throwable t) { 
      System.out.println(t); 
     } 
     return null; 

    } 

    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
     try { 
      sshconnectionTest sshcon = new sshconnectionTest(); 
      String command1 = " env | grep CCM;"; 
      String session = sshcon.getSession(command1); 
      String command = "export SRL_FILE=/home/20140224/myfile.txt;"; 
      sshcon.getSession(command); 
      sshcon.getSession("env | grep SRL;"); 
      sshcon.getSession("pwd"); 
     } catch (Exception e) { 
     } 

    } 

} 
` 

回答

0

每次调用getSession()时候你得到一个新的会话。这就是为什么每个命令都在不同的shell中执行,因为它是不同的shell。

取而代之,让您的会话在您的main()一次,保持该对象。然后重新使用它。

除了getSession()之外,您还需要其他方法,更不用说“get session”对于在远程shell执行命令的方法不是一个好名字。这不仅仅是开会,而是做其他事情。这违反了最不惊讶的原则,即。每种方法都应该只做一件事。

创建一个新的方法,称为:executeRemoteCommand(String command)并使用它来执行您的命令。您可以使用getSession()一次,并将会话存储在可从每种方法访问的对象中,即。一个实例变量。或者您可以将您的会话传递给您的executeRemoteCommand()方法。就像:executeRemoteCommand(Session session, String command)

下面是我过去如何做的一个例子(不会假装这段代码是完美的......但它应该给你一些想法)。这用于通过sFTP从Linux服务器发送和接收文件。经过一些修改,它可以发送几乎任何命令到你想要的远程shell。

package com.somecompany.productfeed; 

import net.snakedoc.jutils.ConfigException; 

import org.apache.log4j.Logger; 

import com.jcraft.jsch.Channel; 
import com.jcraft.jsch.ChannelSftp; 
import com.jcraft.jsch.JSch; 
import com.jcraft.jsch.JSchException; 
import com.jcraft.jsch.Session; 
import com.jcraft.jsch.SftpException; 

public class SFTP { 

    // setup logger 
    private static final Logger LOG = Logger.getLogger(SFTP.class.getName()); 

    private JSch jsch; 
    private ChannelSftp sftpChannel; 
    private Session session; 

    private String username; 
    private String password; 
    private String host; 
    private int port; 

    // singleton 
    private volatile static SFTP instance = null; 

    /** 
    * Private constructor used in Singleton pattern. 
    *  All variables populated via properties file upon 
    *  object instantiation. Since we only need FTP to one server, 
    *  object variables are immutable after instantiation. 
    * 
    * @throws ConfigException 
    * @throws NumberFormatException 
    */ 
    private SFTP() throws ConfigException, NumberFormatException { 

     this.jsch = new JSch(); 
     this.username = Config.getInstance().getConfig("SFTP_USER"); 
     this.password = Config.getInstance().getConfig("SFTP_PASS"); 
     this.host = Config.getInstance().getConfig("SFTP_HOST"); 
     this.port = Integer.parseInt(Config.getInstance().getConfig("SFTP_PORT")); 

    } 

    /** 
    * Create or Return SFTP Object using Singleton pattern. 
    * 
    * @return Singleton of SFTP Object. 
    * @throws NumberFormatException 
    * @throws ConfigException 
    */ 
    public static SFTP getInstance() throws NumberFormatException, ConfigException { 

     if (SFTP.instance == null) { 

      synchronized (SFTP.class) { 

       if (SFTP.instance == null) { 

        SFTP.instance = new SFTP(); 

       } 

      } 

     } 

     return SFTP.instance; 

    } 

    /** 
    * If connection is not already open/connected, open connection. 
    * 
    * @throws JSchException 
    */ 
    public void openConnection() throws JSchException { 

     LOG.info("Opening SFTP Connection"); 
     if (null == getSession() || ! getSession().isConnected()) { 

      setSession(jsch.getSession(this.username, this.host, this.port)); 
      getSession().setConfig("StrictHostKeyChecking", "no"); 
      getSession().setPassword(this.password); 
      getSession().connect(); 

      Channel channel = getSession().openChannel("sftp"); 
      channel.connect(); 
      setSftpChannel((ChannelSftp) channel); 

     } else { 

      LOG.info("SFTP Connection already open"); 

     } 

     LOG.debug("Success"); 

    } 

    /** 
    * Closes connection. 
    */ 
    public void closeConnection() { 

     LOG.info("Closing SFTP connection"); 
     getSftpChannel().exit(); 
     getSession().disconnect(); 
     LOG.debug("SFTP Connection closed"); 

    } 

    /** 
    * Checks if SFTP Connection is open. 
    * 
    * @return TRUE if connection is open, FALSE if connection is closed 
    */ 
    public boolean isOpen() { 

     if (getSession().isConnected()) { 

      return true; 

     } else { 

      return false; 

     } 

    } 

    /** 
    * Gets SFTP Channel 
    * 
    * @return SFTP Channel (<code>ChannelSftp</code>) 
    */ 
    private ChannelSftp getSftpChannel() { 

     return this.sftpChannel; 

    } 

    /** 
    * Returns current <code>Session</code> 
    * 
    * @return <code>Session</code> 
    */ 
    private Session getSession() { 

     return this.session; 

    } 

    /** 
    * Sets SFTP Channel (<code>ChannelSftp</code>) 
    * 
    * @param sftpChannel Channel to set this object's <code>ChannelSftp</code> 
    */ 
    private void setSftpChannel(ChannelSftp sftpChannel) { 

     this.sftpChannel = sftpChannel; 

    } 

    /** 
    * Sets current <code>Session</code> 
    * 
    * @param session Sets this object's <code>Session</code> 
    */ 
    private void setSession(Session session) { 

     this.session = session; 

    } 

    /** 
    * Pushes local file to remote location 
    * 
    * @param local String representation of filepath + filename (ex: /some_local_directory/somefile.txt) 
    * @param remote String representation of filepath + filename (ex: /some_remote_directory/somefile.txt) 
    * @throws SftpException 
    */ 
    public void push(String local, String remote) throws SftpException { 

     LOG.info("Sending file: " + local + " to remote: " + remote); 
     getSftpChannel().put(local, remote); 
     LOG.debug("Success"); 

    } 

    /** 
    * Gets remote file to local location 
    * 
    * @param remote String representation of filepath + filename (ex: /some_remote_directory/somefile.txt) 
    * @param local String representation of filepath + filename (ex: /some_local_directory/somefile.txt) 
    * @throws SftpException 
    */ 
    public void get(String remote, String local) throws SftpException { 

     LOG.info("Retrieving file: " + remote + " saving to: " + local); 
     getSftpChannel().get(remote, local); 
     LOG.debug("Success"); 

    } 

} 
+0

我做了相同的更改,但仍然需要不同的shell。它不会保留相同的外壳。 – Sachin

+1

如果您使用相同的连接,会话和通道,那么它将会是相同的shell。你做错了什么......:/ ...仔细看看我是怎么做到的。我设置了私有字段一次,然后离开它们(包括jsch,channel和session对象,这意味着,每次使用同一个对象时,它都是一样的。 – SnakeDoc