(Moved comments here to include more information.)
The SIGHUP
part in the accepted answer is not correct.
Upon that exit, the master side of the pty pair is closed which means the pty is destroyed, so processes controlled by the slave will receive a SIGHUP.
This is not the case. According to POSIX, "If a modem disconnect is detected by the terminal interface for a controlling terminal [...] the SIGHUP
signal shall be sent to the controlling process." For ssh -t 'sleep 2 &'
, it's the controlling process exiting which causes the tty disconnect so SIGHUP
cannot be sent to the controlling process since it's already dead. The sleep
is killed by SIGHUP
is actually because when the session leader exits, "the SIGHUP
signal shall be sent to each process in the foreground process group".
The confusing part is in sleep 2 &
. Yes it's a command running in background but it's not part of a background process group. Background process group is related to job control which is by default disabled in non-interactive shell (as in ssh ... 'sleep 2 &'
). Actually the sleep 2 &
is running in the foreground process group. For example:
$ ssh -t localhost 'sleep 2 & ps jt'
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
88819 88825 88825 88825 pts/36 88825 Ss+ 0 0:00 bash -c sleep 2 & ps jt
88825 88826 88825 88825 pts/36 88825 S+ 0 0:00 sleep 2
88825 88827 88825 88825 pts/36 88825 R+ 0 0:00 ps jt
As we can see, all the processes' PGID (88825) is the same as PID of the bash shell and TPGID is also 88825. That's to say the background process sleep 2 &
is also in this foreground process group.
For comparison, see
$ pgrep -af sleep
$ ssh -t localhost 'set -m; sleep 123 & ps jt'
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
89002 89008 89008 89008 pts/3 89010 Ss 0 0:00 bash -c set -m; sleep 123 & ps jt
89008 89009 89009 89008 pts/3 89010 S 0 0:00 sleep 123
89008 89010 89010 89008 pts/3 89010 R+ 0 0:00 ps jt
Connection to localhost closed.
$ ps j 89009
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1 89009 89009 89008 ? -1 S 0 0:00 sleep 123
$
As we can see, with job control enabled (set -m
), sleep 2 &
is running in its own process group (PGID 89009) which is a background process group. And after ssh
terminates, the sleep
is still running.
(See a similar scenario for more discussion: Expect + "ssh -f" does not work)
nohup
to keep a script running like that. (You might also consider starting long-running jobs inside oftmux
so you can monitor their progress interactively, but a log file works fine.) – jpaugh Feb 21 '17 at 17:27sshd
orxterm
use it, the mechanism is there and there is a way to know this. At least one terminal emulator, mine, does use it and terminates when the line discipline drops virtual DTR. – JdeBP Feb 21 '17 at 18:19firefox &!
and that prevents a terminal emulator from closing) – Stéphane Chazelas Feb 21 '17 at 21:17