hierynomus / sshj

ssh, scp and sftp for java
Apache License 2.0
2.5k stars 601 forks source link

Commands executed with xargs returns exit status null #304

Open eliasarias95 opened 7 years ago

eliasarias95 commented 7 years ago

Hi and thank you for writing this library!

I am developing a tool to manage long-lived java processes across a handful of servers. To kill processes, I have opted for the following solution: pgrep -f blah | xargs kill. Using your library, this command successfully kills jobs, but I encounter a runtime exception I get an exit status that is null. The backend of this software passes the exit status to the web app and so it is important to tell the user the process was successfully killed.

Any idea what is happening here? Any suggestions to avoid this problem?

Thanks again!

hierynomus commented 7 years ago

Hi Elias,

What is the exit code you get when you execute this on the command line?

eliasarias95 commented 7 years ago

I get an exit code 0 when executing on the command line.

hierynomus commented 7 years ago

Is this only with | xargs kill? Does it happen with other piped commands?

Do you have a small reproduction case (integration test?) for me to debug?

eliasarias95 commented 7 years ago

It looks like the culprit is xargs. Before choosing this logic for killing processes, I was using a long and nasty ps ax command with plenty of pipes, so piped commands seem okay.

I'm not the best developer, but here are the main code snippets that should give you the ability to easily debug.

public void killJob() throws IOException {
        final SSHClient ssh = new SSHClient();
        ssh.loadKnownHosts();
        ssh.connect("server");
        String key = File.separator + "home" + File.separator + "user" + PRIVATE_KEY;
        ssh.authPublickey("user", key);
        exec(ssh, "pgrep -f process_to_kill | xargs kill");
        ssh.disconnect();
    }

private void exec(SSHClient ssh, String cmd) throws ConnectionException, TransportException, IOException {
        final Session s = ssh.startSession();
        try {
            final Command c = s.exec(cmd);
            LOG.info(IOUtils.readFully(c.getInputStream()).toString());
            c.join(5, TimeUnit.MINUTES);
            LOG.info("Exit status: " + c.getExitStatus());
            if (c.getExitErrorMessage() != null) {
                LOG.error("Command " + cmd + " failed to execute: " + c.getExitErrorMessage());
                throw new RuntimeException();
            }
        } finally {
            s.close();
        }
    }

I hope this helps! This is my first time interacting with other git users, so please don't feel like you are condescending me if you give extra or redundant information. I can use all the help I can get haha.

Cheers, -Elias Arias

CoderUtk commented 2 years ago

I think this issue of getting exitStatus as null is with pipe based commands. Faced the same issue with following command. kill $(ps ax | grep -i module.sh | awk '{ print $1 }'