ssh command unexpectedly continues on other system after ssh terminates
uther's answer tells you to allocate a terminal but doesn't explain why. The reason is not specific to ssh, it is a matter of signal generation and propagation. I invite you to read What causes various signals to be sent? for more background.
On the remote host, there are two relevant processes:
- an instance of the ssh daemon (
sshd), which is relaying the input and output of the remote program to the local terminal;
- a shell, which is running that
The shell can die either naturally when it reaches the end of the loop or experiences a fatal error, or to a signal. The question is, why would the shell receive a signal?
If the remote shell is connected to
sshd over pipes, which is what happens when you specify a command on the
ssh command line, then it will die of a SIGPIPE if
sshd exits and the shell tries to write to the pipe. As long as the shell isn't writing to the pipe, it won't receive a SIGPIPE. Here, the shell is never writing anything to its standard output, so it can live forever.
You can pass the
-t option to ssh, to tell it to emulate a terminal on the remote side and run the specified command in this terminal. Then, if the SSH client disappears,
sshd closes the connection and exits, destroying the terminal. When the terminal device goes away, any process running in it receives a SIGHUP. So if you kill the SSH client (with
kill, or by closing the terminal that the client is running in), the remote shell is SIGHUPped.
If you pass the
-t option, SSH also relays SIGINT. If you press Ctrl+C, then the remote shell receives a SIGINT.
Try allocating a psuedo-tty with your
ssh -t $ip_address 'for n in 1 2 3 4 5; do sleep 10; echo $n >>/tmp/count; done'
When you disconnect the ssh session, the process should terminate.
Since this is a pseudo-tty, your shell initialization is probably not going to source configuration files, leaving your command with a very bare environment. You may need to set up a
.ssh/environment file that defines environment variables such as PATH. From
man 1 ssh
Additionally, ssh reads ~/.ssh/environment, and adds lines of the format “VARNAME=value” to the environment if the file exists and users are allowed to change their environment. For more information, see the PermitUserEnvironment option in sshd_config(5).
As an alternative to using the
-t option to
ssh to make the remote command terminate when the
ssh client exits or (gets killed), a named pipe can be used to convert "EOF to SIGHUP" when the stdin of
sshd is being closed (see Bug 396 - sshd orphans processes when no pty allocated).
# sample code in Bash # press ctrl-d for EOF ssh localhost ' TUBE=/tmp/myfifo.fifo rm -f "$TUBE" mkfifo "$TUBE" #exec 3<>"$TUBE" <"$TUBE" sleep 100 & appPID=$! # cf. "OpenSSH and non-blocking mode", # http://lists.mindrot.org/pipermail/openssh-unix-dev/2005-July/023090.html #cat >"$TUBE" #socat -u STDIN "PIPE:$TUBE" dd of="$TUBE" bs=1 2>/dev/null #while IFS="" read -r -n 1 char; do printf '%s' "$char"; done > "$TUBE" #kill -HUP -$appPID kill $appPID rm -f "$TUBE" '