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
链接地址: http://www.djcxy.com/p/97124.html
上一篇: 用ssh检查远程主机上是否存在文件
下一篇: 终止由bash脚本执行的SSH会话