Search code examples
javashellunixsshweblogic

"Sudo su - weblogic" via a Java Program?


I am trying to connect my remote unix machine and execute some ssh commands using a java program.

connection = new Connection(hostname);                                                  
connection.connect();
boolean isAuthenticated = connection.authenticateWithPassword(username, password);
if (isAuthenticated == false)
    throw new IOException("Authentication failed.");    
Session session = connection.openSession();
session.execCommand("sudo su - weblogic");  

Here it needs password again & ofcrs, I can't provide because there is no terminal. So created a user.sh file @ my unix user home direcotry (/home/..../bharat) with below content.

echo <mypassword> | sudo -S su - weblogic
sudo -S su - weblogic

but now if I call bash user.sh like below

session.execCommand("bash user.sh"); 

after logging in with my user in java, it gives below error & could not figure out the resolution for this yet.

sudo: sorry, you must have a tty to run sudo
sudo: sorry, you must have a tty to run sudo

Please help :)

The Response of Send("cd /u02/app/oracle/xyz/admin/domains/11.1.1.9/xxxx_xx_xxx_xxx.domain/shared/logs/xxxx"); is below -

Highlighted Red ==> shows the response, I am getting as of now.

Highlighted Blue ==> Expected response.

Highlighted Green ==> works fine if I send 4 smaller commands by splitting the same command.

enter image description here


Solution

  • As you and @rkosegi say, su needs a terminal session for the password.

    It looks like the Ganymed SSH-2 library in the example? This has an option for a shell session. Clearly you now need to handle reading and writing through stdout and stdin directly though.

    For example, with a couple of methods to keep it simpler:

    public class SshTerminal {
        private Connection connection;
        private Session session;
    
        private Reader reader;
        private PrintWriter writer;
        private String lastResponse;
    
        public SshTerminal(String hostname, String username, String password)
                throws JSchException, IOException {
            connection = new Connection(hostname);
            connection.connect();
            boolean isAuthenticated = connection.authenticateWithPassword(username,
                    password);
            if (isAuthenticated == false)
                throw new IOException("Authentication failed.");
            session = connection.openSession();
            session.requestDumbPTY();
            session.startShell();
    
            writer = new PrintWriter(session.getStdin());
            reader = new InputStreamReader(session.getStdout());
        }
    
        public void send(String command) {
            writer.print(command + "\n");
            writer.flush();
        }
    
        public void waitFor(String expected) throws IOException {
            StringBuilder buf = new StringBuilder();
            char[] chars = new char[256];
            while (buf.indexOf(expected) < 0) {
                int length = reader.read(chars);
                System.out.print(new String(chars, 0, length));
                buf.append(chars, 0, length);
            }
    
            int echoEnd = buf.indexOf("\n");
            int nextPrompt = buf.lastIndexOf("\n");
            if (nextPrompt > echoEnd)
                lastResponse = buf.substring(echoEnd + 1, nextPrompt);
            else
                lastResponse = "";
        }
    
        public String getLastResponse() {
            return lastResponse;
        }
    
        public void disconnect() {
            session.close();
            connection.close();
        }
    }
    

    This then worked fine:

        SshTerminal term = new SshTerminal(host, username, password);
    
        term.waitFor("$ ");
        term.send("su -");
        term.waitFor("Password: ");
        term.send(rootPassword);
        term.waitFor("# ");
        term.send("ls /root");
        term.waitFor("# ");
        term.send("cat /file-not-found 2>&1");
        term.waitFor("# ");
    
        term.send("cat /var/log/messages");
        term.waitFor("# ");
        String logFileContent = term.getLastResponse();
    
        term.send("exit");
        term.waitFor("$ ");
        term.send("exit");
    
        term.disconnect();
    
        String[] lines = logFileContent.split("\n");
        for (int i = 0; i < lines.length; i++)
            logger.info("Line {} out of {}: {}", i + 1, lines.length, lines[i]);
    

    That includes examples of parsing the lines in a response, and forcing error output through.

    Clearly some of the responses there might be different in your environment.