Terminating SSH session executed by bash script
I have a script I can run locally to remotely start a server:
#!/bin/bash
ssh user@host.com <<EOF
  nohup /path/to/run.sh &
EOF
echo 'done'
After running nohup, it hangs. I have to hit ctrl-c to exit the script.
I've tried adding an explicit exit at the end of the here doc and using "-t" argument for ssh. Neither works. How do I make this script exit immediately?
EDIT: The client is OSX 10.6, server is Ubuntu.
 I think the problem is that nohup can't redirect output when you come in from ssh, it only redirects to nohup.out when it thinks its connected to a terminal, and I the stdin override you have will prevent that, even with -t .  
A workaround might be to redirect the output yourself, then the ssh client can disconnect - it's not waiting for the stream to close. Something like:
nohup /path/to/run.sh > run.log &
(This worked for me in a simple test connecting to an Ubuntu server from an OS X client.)
The problem might be that ...
... ssh is respecting the POSIX standard when not closing the session 
if a process is still attached to the tty.
 Therefore a solution might be to detach the stdin of the nohup command from the tty:  
nohup /path/to/run.sh </dev/null &
See: SSH Hangs On Exit When Using nohup
 Yet another approach might be to use ssh -t -t to force pseudo-tty allocation even if stdin isn't a terminal.  
man ssh | less -Ip 'multiple -t'
ssh -t -t user@host.com <<EOF
  nohup /path/to/run.sh &
EOF
See: BASH spawn subshell for SSH and continue with program flow
 Redirecting the stdin of the remote host from a here document while invoking ssh without an explicit command leads to the message: Pseudo-terminal will not be allocated because stdin is not a terminal.  
 To avoid this message either use ssh 's -T switch to tell the remote host there is no need to allocate a pseudo-terminal or explicitly specify a command (such as /bin/sh ) for the remote host to execute the commands provided by the here document.  
 If an explicit command is given to ssh , the default is to provide no login shell in the form of a pseudo-terminal, ie there will be no normal login session when a command is specified (see man ssh ).  
 Without a command specified for ssh , on the other hand, the default is to create a pseudo-tty for an interactive login session on the remote host.  
- ssh user@host.com <<EOF
+ ssh -T user@host.com <<EOF
+ ssh user@host.com /bin/bash <<EOF
 As a rule, ssh -t or even ssh -t -t should only be used if there are commands that expect stdin / stdout to be a terminal (such as top or vim ) or if it is necessary to kill the remote shell and its children when the ssh client command finishes execution (see: ssh command unexpectedly continues on other system after ssh terminates).  
 As far as I can tell, the only way to combine an ssh command that does not allocate a pseudo-tty and a nohup command that writes to nohup.out on the remote host is to let the nohup command execute in a pseudo-terminal not created by the ssh mechanism.  This can be done with the script command, for example, and will avoid the tcgetattr: Inappropriate ioctl for device message.  
#!/bin/bash
ssh localhost /bin/sh <<EOF
  #0<&-  script -q /dev/null nohup sleep 10 1>&- &
  #0<&- script -q -c "nohup sh -c 'date; sleep 10 1>&- &'" /dev/null  # Linux
  0<&- script -q /dev/null nohup sh -c 'date; sleep 10 1>&- &'        # FreeBSD, Mac OS X
  cat nohup.out
  exit 0
EOF
echo 'done'
exit 0
上一篇: 用ssh检查远程主机上是否存在文件
下一篇: 终止由bash脚本执行的SSH会话
