4

I am trying to execute a command on a Linux server using SSH from Android with JSch.

As far as I know I am connecting to the server, but when I attempt to retrieve the results of the command I am getting nothing.

Connect to server:

public class SSHCommand {

    public static String executeRemoteCommand(
            String username,
            String password,
            String hostname,
            int port) throws Exception {

        JSch jsch = new JSch();
        Session session = jsch.getSession(username, hostname, port);
        session.setPassword(password);

        // Avoid asking for key confirmation
        Properties prop = new Properties();
        prop.put("StrictHostKeyChecking", "no");
        session.setConfig(prop);

        session.connect();

        // SSH Channel
        ChannelExec channelssh = (ChannelExec)
                session.openChannel("exec");
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        channelssh.setOutputStream(baos);

        // Execute command
        channelssh.setCommand("ls");
        channelssh.connect();
        channelssh.disconnect();

        return baos.toString();
    }
}

Retrieve data:

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final String TAG = "TESTING";

        new AsyncTask<Integer, Void, Void>(){
            @Override
            protected Void doInBackground(Integer... params) {
                try {
                    Log.d(TAG, SSHCommand.executeRemoteCommand("username", "password", "192.168.0.1", 22));
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
        }.execute(1);
    }
}

What am I missing here?

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Will
  • 1,487
  • 1
  • 23
  • 35

2 Answers2

8

You disconnect immediately after you start the command, before any output is returned.

You have to wait for the "exec" channel to close (it closes once the command finishes).

See the official JSch example for the "exec" channel.

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()){
    if(in.available()>0) continue; 
    System.out.println("exit-status: "+channel.getExitStatus());
    break;
  }
  try{Thread.sleep(1000);}catch(Exception ee){}
}

Though to allow the command to reliably complete and to collect all output including the errors, see How to read JSch command output?

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
0

It worked for me after I put my crafted code after channelssh.connect();

            while(true){
                if(channelssh.isClosed()){
                    break;
                }
            }

So my completed function would be:

            public static String executeRemoteCommand(
            String username,
            String password,
            String hostname,
            int port) throws Exception {

        try{
            JSch jsch = new JSch();
            Session session = jsch.getSession(username, hostname, 22);
            session.setPassword(password);

            // Avoid asking for key confirmation
            Properties prop = new Properties();
            prop.put("StrictHostKeyChecking", "no");
            session.setConfig(prop);

            session.connect();

            // SSH Channel
            ChannelExec channelssh = (ChannelExec) session.openChannel("exec");
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            channelssh.setOutputStream(baos);

            // Execute command
            channelssh.setCommand("ls -al");

            channelssh.connect();

            while(true){
                if(channelssh.isClosed()){
                    break;
                }
            }

            channelssh.disconnect();

            return baos.toString();
        } catch (Exception e){
            Log.e("Some Tag", e.getMessage());

            return "ERROR";
        }

    }
Shy Devil
  • 9
  • 4
  • This is basically the same as in the documentation page but simplified (https://shy-devils.life-is-pa.in/ZB5rKb) – Shy Devil May 10 '21 at 16:10
  • 1
    Your `while(true)` loop will spin CPU core unnecessarily. And it can be simplified to `while (!channelssh.isClosed()) {}` – Martin Prikryl May 10 '21 at 17:39
  • Might be true i didn't try it and my focus was trying to get it to work :) . But I'm glad you help too – Shy Devil May 10 '21 at 17:55