The 'exit' command doesn't work for my case, and I don't get it why:
ssh user@mysever <<'HEREDOC'
echo "1. Running PM2 log..."
pm2 log &
echo "2. PM2 log is now in background"
exit
echo "3. Won't be here"
HEREDOC
echo "4. Out."
I can't terminate the ssh pipeline, even with the 'exit' command above.
I can see the first echo, second echo; no third echo of course; and stuck. I expected the behaviour that I can see the fourth echo. I have to press Ctrl+C, and I see the 4th echo after that.
Short answer: You should redirect the standard input, output, and error for the
pm2
process:This will prevent the remote ssh server from holding the session open until pm2 exits.
Longer answer:
When you run
ssh
in this fashion, the remote ssh server will launch a copy of the remote user's shell to handle the session. To relay input and output from the remote session, the remote ssh server will allocate either a TTY or a set of pipes. Then it sets the TTY or pipes as the standard input, output, and error for the shell process.So, on the remote system, you have either a TTY or a set of pipes connecting the remote shell process to the SSH server process. Any commands invoked by the shell will inherit the TTY or set of pipes as the command's standard input etc. (unless you use shell features to redirect the standard file handles).
You might think that the ssh server will terminate the session when the remote shell process exits. But that's not what happens. The ssh server terminates the session when it reads an end-of-file condition on the TTY or the pipe connected to the standard output for the session.
In your case, you're invoking this
pm2
command on the remote system, and it's inheriting the remote session's standard output. As long as this program is running, the remote ssh server won't get an EOF on the standard output pipe and it won't terminate the session.The fix is to redirect input for the
pm2
process so it doesn't inherit the standard handles that are connected to the ssh server:You could redirect to a file instead of /dev/null if you want to capture the output. I think only the standard output redirection is strictly necessary, but you should redirect standard input and error as well just to be sure.
Found the reason why, ssh tunnel wait until termination of stdout (EOF), and no processes reading stdin.