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, i. e. 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