I am running the following SSH command:

ssh "root@$ip" 'nohup sh -s' < ./do_sync &

My goal is to execute the contents of do_sync (a shell script) on the remote host. I'm doing it this way because, for reasons I won't go into, I can't transfer the actual script file to that machine and execute it there.

Not sure if it's relevant, but the remote machine is actually an Android x86 device. However, I'm not doing anything Android-related on it. The Java VM isn't even running. It's just Android's version of Linux, with some busybox utilities on it. It has no bash and the sh it uses seems very basic/old. I'm not sure if it's fully POSIX compliant. It hasn't been until now that I've run into issues getting the behavior I want, so just in case it's OS-related I wanted to mention this detail.

This command works, but the ssh process remains active in the background. What I expect to happen is this:

  1. Execute the SSH command in the background so that the script returns immediately.
  2. The SSH command should connect to the host, execute the sh -s ... commands and immediately return.
  3. The SSH process from step 1 should end

Can someone help me get this behavior? Note that the machine I execute all of this on has bash, and newer version of sh. But the remote SSH host does not have bash, only a very old version of sh. Not sure if that will matter, but thought I'd share anyway.


I tried this as well but the behavior is the same:

cat ./do_sync | ssh "root@$ip" &

EDIT: Realized this is invalid, because I omitted the nohup part, but this ended up having the same blocking behavior:

cat ./do_sync | ssh "root@$ip" "nohup sh -s"


Tried this as well, still blocks the SSH connection from disconnecting:

commands="$(cat ./do_sync)"
ssh "root@$ip" "nohup sh -c $commands"

In this case for some reason sh -s didn't work at all.

  • The sh -s process may not actually read the whole script to the end as soon as possibly, but only to the point it needs to to run it. This keeps the connection open. I'm assuming that when it reaches the end of input, the connection is terminated. Transferring the script to the remote host and running it there would alleviate this.
    – Kusalananda
    Dec 3, 2019 at 19:13
  • the script changes constantly. i cant do that. Dec 3, 2019 at 19:40
  • What would be wrong with transferring the script to a file and running it on the remote system? The next time you run the command, you would transfer a new copy of the script.
    – Kusalananda
    Dec 3, 2019 at 19:50
  • How should I transfer a copy of the script? I do not have scp on the remote host and it cannot be added. Dec 3, 2019 at 19:54
  • ssh remote 'cat >./do_sync && nohup sh ./do_sync &' <./do_sync or something (untested)
    – Kusalananda
    Dec 3, 2019 at 20:00

2 Answers 2


The trick with nohup sometimes is to redirect all three standard streams. This should work for you:

cat ./do_sync | ssh root@ip "cat > /tmp/do_sync && chmod 777 /tmp/do_sync ;  nohup /tmp/do_sync 2>/dev/null >/dev/null </dev/null &"

But without the redirections for nohup, it will block.

  • I had almost exactly the same issue, except that my new process was launched inside a script I called from ssh. in local tests it was fine, only blocked when I called the script from SSH. This is how I fixed it in my script: nohup ./longrunningscript.sh >/dev/null 2>/dev/null </dev/null &
    – panschk
    Jun 28, 2021 at 11:26

An alternative approach would be

cat do_sync | ssh "root@ip" 'nohup sh -s'

I'm assuming the effect you see is because you're executing ./do_sync in the background. It only appears that the process still hangs. Unless you're actually seeing an open connection?

  • In this case the SSH process still did not exit. Dec 3, 2019 at 19:49
  • Did you try as is or with the extra & in the edit to your question? Also could it be a command in the do_sync command that is actually still running on the target machine?
    – Bram
    Dec 3, 2019 at 19:50
  • My edit was flawed, and not related to your answer (we were apparently thinking of a similar approach at the same time). Mine is incorrect because the script runs commands that block for a long time. So the invocation of the script contents itself must be done in the background. In a way I'm trying to treat the script as a function, and run that function in the background. I did try yours and it still didn't exit. I need to use & when I invoke ssh because I don't want to wait for the SSH connection to establish. Dec 3, 2019 at 19:54
  • Your command actually causes my terminal to block. Not sure why. Dec 3, 2019 at 19:55
  • your terminal blocks because it is waiting for the nohup'ed command to complete. The & you add is sending the local command (the ssh connection) to the background it does not run the remote command in the background.
    – Bram
    Dec 3, 2019 at 20:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .