Search code examples
javabashsshpipesshj

sshj: How to pipe input to automated host-side script


So, here's the situation:

I would like to use the sshj library to connect to a host which automatically runs a script on connection. Let's say the script merely logs whatever json formated input it receives. In the terminal I can run something like:

echo '{ "name" : "Hubert", "status" : "alive" }' | ssh -i ~/.ssh/id_ed25519 [email protected]

and upon connection the host would log the info { "name" : "Hubert", "status" : "alive" }.

What would an (equivalent) implementation of the above command look like in sshj?


Solution

  • Okay, I am not 100% sure whether all I do in the following code is entirely necessary, but it works for me:

    final SSHClient ssh = new SSHClient();
    /* 
     * Connect to host and authenticate
     */
    try (Session session = ssh.startSession()){
            // open a shell on host
            final Shell shl = session.startShell();
            
            // just a thread to stream stdout of host
            Thread t = new Thread() {
                    @Override
                    public void run() {
                            try {
                                    InputStream in = shl.getInputStream();
                                    BufferedReader br = new BufferedReader(new InputStreamReader(in));
                                    String line;
                                    while ((line = br.readLine()) != null) {
                                            System.out.println("## " + line);
                                    }
                            } catch (Exception e) {
                                    e.printStackTrace();
                            }
                    }
            };
            t.start();
    
            // another thread to stream stderr of host
            Thread err_t = new Thread() {
                    @Override
                    public void run() {
                            try {
                                    InputStream in = shl.getErrorStream();
                                    BufferedReader br = new BufferedReader(new InputStreamReader(in));
                                    String line;
                                    while ((line = br.readLine()) != null) {
                                            System.out.println("## " + line);
                                    }
                            } catch (Exception e) {
                                    e.printStackTrace();
                            }
                    }
            };
            err_t.start();
            
            // you might want to escape the input string
            String input = "Some String";
            byte[] data = input.getBytes();
            // getOutputStream() corresponds to the hosts stdin
            OutputStream out = shl.getOutputStream();
            out.write(data);
            // ensure all written bytes get flushed to host
            out.flush();
            out.close();
            shl.join(5, TimeUnit.SECONDS);
            shl.close();
        } finally {
            ssh.disconnect();
        }