Saturday, April 23, 2022

[SOLVED] nohup doesn't work when used with double-ampersand (&&) instead of semicolon (;)

Issue

I have a script that uses ssh to login to a remote machine, cd to a particular directory, and then start a daemon. The original script looks like this:

ssh server "cd /tmp/path ; nohup java server 0</dev/null 1>server_stdout 2>server_stderr &"

This script appears to work fine. However, it is not robust to the case when the user enters the wrong path so the cd fails. Because of the ;, this command will try to run the nohup command even if the cd fails.

The obvious fix doesn't work:

ssh server "cd /tmp/path && nohup java server 0</dev/null 1>server_stdout 2>server_stderr &"

that is, the SSH command does not return until the server is stopped. Putting nohup in front of the cd instead of in front of the java didn't work.

Can anyone help me fix this? Can you explain why this solution doesn't work? Thanks!

Edit: cbuckley suggests using sh -c, from which I derived:

ssh server "nohup sh -c 'cd /tmp/path && java server 0</dev/null 1>master_stdout 2>master_stderr' 2>/dev/null 1>/dev/null &"

However, now the exit code is always 0 when the cd fails; whereas if I do ssh server cd /failed/path then I get a real exit code. Suggestions?


Solution

Answer roundup:

  • Bad: Using sh -c to wrap the entire nohup command doesn't work for my purposes because it doesn't return error codes. (@cbuckley)
  • Okay: ssh <server> <cmd1> && ssh <server> <cmd2> works but is much slower (@joachim-nilsson)
  • Good: Create a shell script on <server> that runs the commands in succession and returns the correct error code.

The last is what I ended up using. I'd still be interested in learning why the original use-case doesn't work, if someone who understands shell internals can explain it to me!



Answered By - Dan Halperin
Answer Checked By - Mary Flores (WPSolving Volunteer)